From: Sasha Levin Date: Wed, 25 Oct 2023 11:48:01 +0000 (-0400) Subject: Fixes for 5.15 X-Git-Tag: v6.1.61~82 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=81f256f9a3a6796d7d2f7bc2def85ad8c6eac2ee;p=thirdparty%2Fkernel%2Fstable-queue.git Fixes for 5.15 Signed-off-by: Sasha Levin --- diff --git a/queue-5.15/asoc-codecs-add-wsa883x-amplifier-support.patch b/queue-5.15/asoc-codecs-add-wsa883x-amplifier-support.patch new file mode 100644 index 00000000000..351fcd3bcef --- /dev/null +++ b/queue-5.15/asoc-codecs-add-wsa883x-amplifier-support.patch @@ -0,0 +1,1385 @@ +From 787800e9ddc193ed15b603327bec947ae26b8746 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 29 Jun 2022 10:06:42 +0100 +Subject: ASoC: codecs: add wsa883x amplifier support + +From: Srinivas Kandagatla + +[ Upstream commit 43b8c7dc85a14f36048a27bb6c627fd49144a8d1 ] + +This patch adds support to WSA8830/WSA8812/WSA8835 Class-D Smart +Speaker Amplifier. This Amplifier is primarily interfaced with +SoundWire. + +This patch is tested on SM8450 MTP Board. + +Signed-off-by: Srinivas Kandagatla +Link: https://lore.kernel.org/r/20220629090644.67982-3-srinivas.kandagatla@linaro.org +Signed-off-by: Mark Brown +Stable-dep-of: da29b94ed354 ("ASoC: codecs: wcd938x: fix resource leaks on bind errors") +Signed-off-by: Sasha Levin +--- + sound/soc/codecs/Kconfig | 10 + + sound/soc/codecs/Makefile | 2 + + sound/soc/codecs/wsa883x.c | 1301 ++++++++++++++++++++++++++++++++++++ + 3 files changed, 1313 insertions(+) + create mode 100644 sound/soc/codecs/wsa883x.c + +diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig +index b193db25c37fe..31896c8c2b0d6 100644 +--- a/sound/soc/codecs/Kconfig ++++ b/sound/soc/codecs/Kconfig +@@ -294,6 +294,7 @@ config SND_SOC_ALL_CODECS + imply SND_SOC_WM9712 + imply SND_SOC_WM9713 + imply SND_SOC_WSA881X ++ imply SND_SOC_WSA883X + imply SND_SOC_ZL38060 + help + Normally ASoC codec drivers are only built if a machine driver which +@@ -1838,6 +1839,15 @@ config SND_SOC_WSA881X + This enables support for Qualcomm WSA8810/WSA8815 Class-D + Smart Speaker Amplifier. + ++config SND_SOC_WSA883X ++ tristate "WSA883X Codec" ++ depends on SOUNDWIRE ++ select REGMAP_SOUNDWIRE ++ tristate ++ help ++ This enables support for Qualcomm WSA8830/WSA8835 Class-D ++ Smart Speaker Amplifier. ++ + config SND_SOC_ZL38060 + tristate "Microsemi ZL38060 Connected Home Audio Processor" + depends on SPI_MASTER +diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile +index 5ba164d41b300..4edc4775c7323 100644 +--- a/sound/soc/codecs/Makefile ++++ b/sound/soc/codecs/Makefile +@@ -317,6 +317,7 @@ snd-soc-wm9712-objs := wm9712.o + snd-soc-wm9713-objs := wm9713.o + snd-soc-wm-hubs-objs := wm_hubs.o + snd-soc-wsa881x-objs := wsa881x.o ++snd-soc-wsa883x-objs := wsa883x.o + snd-soc-zl38060-objs := zl38060.o + # Amp + snd-soc-max9877-objs := max9877.o +@@ -649,6 +650,7 @@ obj-$(CONFIG_SND_SOC_WM9713) += snd-soc-wm9713.o + obj-$(CONFIG_SND_SOC_WM_ADSP) += snd-soc-wm-adsp.o + obj-$(CONFIG_SND_SOC_WM_HUBS) += snd-soc-wm-hubs.o + obj-$(CONFIG_SND_SOC_WSA881X) += snd-soc-wsa881x.o ++obj-$(CONFIG_SND_SOC_WSA883X) += snd-soc-wsa883x.o + obj-$(CONFIG_SND_SOC_ZL38060) += snd-soc-zl38060.o + + # Amp +diff --git a/sound/soc/codecs/wsa883x.c b/sound/soc/codecs/wsa883x.c +new file mode 100644 +index 0000000000000..856709ec017e6 +--- /dev/null ++++ b/sound/soc/codecs/wsa883x.c +@@ -0,0 +1,1301 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* ++ * Copyright (c) 2015-2021, The Linux Foundation. All rights reserved. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define WSA883X_BASE 0x3000 ++#define WSA883X_ANA_BG_TSADC_BASE (WSA883X_BASE + 0x00000001) ++#define WSA883X_REF_CTRL (WSA883X_ANA_BG_TSADC_BASE + 0x0000) ++#define WSA883X_TEST_CTL_0 (WSA883X_ANA_BG_TSADC_BASE + 0x0001) ++#define WSA883X_BIAS_0 (WSA883X_ANA_BG_TSADC_BASE + 0x0002) ++#define WSA883X_OP_CTL (WSA883X_ANA_BG_TSADC_BASE + 0x0003) ++#define WSA883X_IREF_CTL (WSA883X_ANA_BG_TSADC_BASE + 0x0004) ++#define WSA883X_ISENS_CTL (WSA883X_ANA_BG_TSADC_BASE + 0x0005) ++#define WSA883X_CLK_CTL (WSA883X_ANA_BG_TSADC_BASE + 0x0006) ++#define WSA883X_TEST_CTL_1 (WSA883X_ANA_BG_TSADC_BASE + 0x0007) ++#define WSA883X_BIAS_1 (WSA883X_ANA_BG_TSADC_BASE + 0x0008) ++#define WSA883X_ADC_CTL (WSA883X_ANA_BG_TSADC_BASE + 0x0009) ++#define WSA883X_DOUT_MSB (WSA883X_ANA_BG_TSADC_BASE + 0x000A) ++#define WSA883X_DOUT_LSB (WSA883X_ANA_BG_TSADC_BASE + 0x000B) ++#define WSA883X_VBAT_SNS (WSA883X_ANA_BG_TSADC_BASE + 0x000C) ++#define WSA883X_ITRIM_CODE (WSA883X_ANA_BG_TSADC_BASE + 0x000D) ++ ++#define WSA883X_ANA_IVSENSE_BASE (WSA883X_BASE + 0x0000000F) ++#define WSA883X_EN (WSA883X_ANA_IVSENSE_BASE + 0x0000) ++#define WSA883X_OVERRIDE1 (WSA883X_ANA_IVSENSE_BASE + 0x0001) ++#define WSA883X_OVERRIDE2 (WSA883X_ANA_IVSENSE_BASE + 0x0002) ++#define WSA883X_VSENSE1 (WSA883X_ANA_IVSENSE_BASE + 0x0003) ++#define WSA883X_ISENSE1 (WSA883X_ANA_IVSENSE_BASE + 0x0004) ++#define WSA883X_ISENSE2 (WSA883X_ANA_IVSENSE_BASE + 0x0005) ++#define WSA883X_ISENSE_CAL (WSA883X_ANA_IVSENSE_BASE + 0x0006) ++#define WSA883X_MISC (WSA883X_ANA_IVSENSE_BASE + 0x0007) ++#define WSA883X_ADC_0 (WSA883X_ANA_IVSENSE_BASE + 0x0008) ++#define WSA883X_ADC_1 (WSA883X_ANA_IVSENSE_BASE + 0x0009) ++#define WSA883X_ADC_2 (WSA883X_ANA_IVSENSE_BASE + 0x000A) ++#define WSA883X_ADC_3 (WSA883X_ANA_IVSENSE_BASE + 0x000B) ++#define WSA883X_ADC_4 (WSA883X_ANA_IVSENSE_BASE + 0x000C) ++#define WSA883X_ADC_5 (WSA883X_ANA_IVSENSE_BASE + 0x000D) ++#define WSA883X_ADC_6 (WSA883X_ANA_IVSENSE_BASE + 0x000E) ++#define WSA883X_ADC_7 (WSA883X_ANA_IVSENSE_BASE + 0x000F) ++#define WSA883X_STATUS (WSA883X_ANA_IVSENSE_BASE + 0x0010) ++ ++#define WSA883X_ANA_SPK_TOP_BASE (WSA883X_BASE + 0x00000025) ++#define WSA883X_DAC_CTRL_REG (WSA883X_ANA_SPK_TOP_BASE + 0x0000) ++#define WSA883X_DAC_EN_DEBUG_REG (WSA883X_ANA_SPK_TOP_BASE + 0x0001) ++#define WSA883X_DAC_OPAMP_BIAS1_REG (WSA883X_ANA_SPK_TOP_BASE + 0x0002) ++#define WSA883X_DAC_OPAMP_BIAS2_REG (WSA883X_ANA_SPK_TOP_BASE + 0x0003) ++#define WSA883X_DAC_VCM_CTRL_REG (WSA883X_ANA_SPK_TOP_BASE + 0x0004) ++#define WSA883X_DAC_VOLTAGE_CTRL_REG (WSA883X_ANA_SPK_TOP_BASE + 0x0005) ++#define WSA883X_ATEST1_REG (WSA883X_ANA_SPK_TOP_BASE + 0x0006) ++#define WSA883X_ATEST2_REG (WSA883X_ANA_SPK_TOP_BASE + 0x0007) ++#define WSA883X_SPKR_TOP_BIAS_REG1 (WSA883X_ANA_SPK_TOP_BASE + 0x0008) ++#define WSA883X_SPKR_TOP_BIAS_REG2 (WSA883X_ANA_SPK_TOP_BASE + 0x0009) ++#define WSA883X_SPKR_TOP_BIAS_REG3 (WSA883X_ANA_SPK_TOP_BASE + 0x000A) ++#define WSA883X_SPKR_TOP_BIAS_REG4 (WSA883X_ANA_SPK_TOP_BASE + 0x000B) ++#define WSA883X_SPKR_CLIP_DET_REG (WSA883X_ANA_SPK_TOP_BASE + 0x000C) ++#define WSA883X_SPKR_DRV_LF_BLK_EN (WSA883X_ANA_SPK_TOP_BASE + 0x000D) ++#define WSA883X_SPKR_DRV_LF_EN (WSA883X_ANA_SPK_TOP_BASE + 0x000E) ++#define WSA883X_SPKR_DRV_LF_MASK_DCC_CTL (WSA883X_ANA_SPK_TOP_BASE + 0x000F) ++#define WSA883X_SPKR_DRV_LF_MISC_CTL (WSA883X_ANA_SPK_TOP_BASE + 0x0010) ++#define WSA883X_SPKR_DRV_LF_REG_GAIN (WSA883X_ANA_SPK_TOP_BASE + 0x0011) ++#define WSA883X_SPKR_DRV_OS_CAL_CTL (WSA883X_ANA_SPK_TOP_BASE + 0x0012) ++#define WSA883X_SPKR_DRV_OS_CAL_CTL1 (WSA883X_ANA_SPK_TOP_BASE + 0x0013) ++#define WSA883X_SPKR_PWM_CLK_CTL (WSA883X_ANA_SPK_TOP_BASE + 0x0014) ++#define WSA883X_SPKR_PWM_FREQ_SEL_MASK BIT(3) ++#define WSA883X_SPKR_PWM_FREQ_F300KHZ 0 ++#define WSA883X_SPKR_PWM_FREQ_F600KHZ 1 ++#define WSA883X_SPKR_PDRV_HS_CTL (WSA883X_ANA_SPK_TOP_BASE + 0x0015) ++#define WSA883X_SPKR_PDRV_LS_CTL (WSA883X_ANA_SPK_TOP_BASE + 0x0016) ++#define WSA883X_SPKR_PWRSTG_DBG (WSA883X_ANA_SPK_TOP_BASE + 0x0017) ++#define WSA883X_SPKR_OCP_CTL (WSA883X_ANA_SPK_TOP_BASE + 0x0018) ++#define WSA883X_SPKR_BBM_CTL (WSA883X_ANA_SPK_TOP_BASE + 0x0019) ++#define WSA883X_PA_STATUS0 (WSA883X_ANA_SPK_TOP_BASE + 0x001A) ++#define WSA883X_PA_STATUS1 (WSA883X_ANA_SPK_TOP_BASE + 0x001B) ++#define WSA883X_PA_STATUS2 (WSA883X_ANA_SPK_TOP_BASE + 0x001C) ++ ++#define WSA883X_ANA_BOOST_BASE (WSA883X_BASE + 0x00000043) ++#define WSA883X_EN_CTRL (WSA883X_ANA_BOOST_BASE + 0x0000) ++#define WSA883X_CURRENT_LIMIT (WSA883X_ANA_BOOST_BASE + 0x0001) ++#define WSA883X_IBIAS1 (WSA883X_ANA_BOOST_BASE + 0x0002) ++#define WSA883X_IBIAS2 (WSA883X_ANA_BOOST_BASE + 0x0003) ++#define WSA883X_IBIAS3 (WSA883X_ANA_BOOST_BASE + 0x0004) ++#define WSA883X_LDO_PROG (WSA883X_ANA_BOOST_BASE + 0x0005) ++#define WSA883X_STABILITY_CTRL1 (WSA883X_ANA_BOOST_BASE + 0x0006) ++#define WSA883X_STABILITY_CTRL2 (WSA883X_ANA_BOOST_BASE + 0x0007) ++#define WSA883X_PWRSTAGE_CTRL1 (WSA883X_ANA_BOOST_BASE + 0x0008) ++#define WSA883X_PWRSTAGE_CTRL2 (WSA883X_ANA_BOOST_BASE + 0x0009) ++#define WSA883X_BYPASS_1 (WSA883X_ANA_BOOST_BASE + 0x000A) ++#define WSA883X_BYPASS_2 (WSA883X_ANA_BOOST_BASE + 0x000B) ++#define WSA883X_ZX_CTRL_1 (WSA883X_ANA_BOOST_BASE + 0x000C) ++#define WSA883X_ZX_CTRL_2 (WSA883X_ANA_BOOST_BASE + 0x000D) ++#define WSA883X_MISC1 (WSA883X_ANA_BOOST_BASE + 0x000E) ++#define WSA883X_MISC2 (WSA883X_ANA_BOOST_BASE + 0x000F) ++#define WSA883X_GMAMP_SUP1 (WSA883X_ANA_BOOST_BASE + 0x0010) ++#define WSA883X_PWRSTAGE_CTRL3 (WSA883X_ANA_BOOST_BASE + 0x0011) ++#define WSA883X_PWRSTAGE_CTRL4 (WSA883X_ANA_BOOST_BASE + 0x0012) ++#define WSA883X_TEST1 (WSA883X_ANA_BOOST_BASE + 0x0013) ++#define WSA883X_SPARE1 (WSA883X_ANA_BOOST_BASE + 0x0014) ++#define WSA883X_SPARE2 (WSA883X_ANA_BOOST_BASE + 0x0015) ++ ++#define WSA883X_ANA_PON_LDOL_BASE (WSA883X_BASE + 0x00000059) ++#define WSA883X_PON_CTL_0 (WSA883X_ANA_PON_LDOL_BASE + 0x0000) ++#define WSA883X_PON_CLT_1 (WSA883X_ANA_PON_LDOL_BASE + 0x0001) ++#define WSA883X_PON_CTL_2 (WSA883X_ANA_PON_LDOL_BASE + 0x0002) ++#define WSA883X_PON_CTL_3 (WSA883X_ANA_PON_LDOL_BASE + 0x0003) ++#define WSA883X_CKWD_CTL_0 (WSA883X_ANA_PON_LDOL_BASE + 0x0004) ++#define WSA883X_CKWD_CTL_1 (WSA883X_ANA_PON_LDOL_BASE + 0x0005) ++#define WSA883X_CKWD_CTL_2 (WSA883X_ANA_PON_LDOL_BASE + 0x0006) ++#define WSA883X_CKSK_CTL_0 (WSA883X_ANA_PON_LDOL_BASE + 0x0007) ++#define WSA883X_PADSW_CTL_0 (WSA883X_ANA_PON_LDOL_BASE + 0x0008) ++#define WSA883X_TEST_0 (WSA883X_ANA_PON_LDOL_BASE + 0x0009) ++#define WSA883X_TEST_1 (WSA883X_ANA_PON_LDOL_BASE + 0x000A) ++#define WSA883X_STATUS_0 (WSA883X_ANA_PON_LDOL_BASE + 0x000B) ++#define WSA883X_STATUS_1 (WSA883X_ANA_PON_LDOL_BASE + 0x000C) ++ ++#define WSA883X_DIG_CTRL_BASE (WSA883X_BASE + 0x00000400) ++#define WSA883X_CHIP_ID0 (WSA883X_DIG_CTRL_BASE + 0x0001) ++#define WSA883X_CHIP_ID1 (WSA883X_DIG_CTRL_BASE + 0x0002) ++#define WSA883X_CHIP_ID2 (WSA883X_DIG_CTRL_BASE + 0x0003) ++#define WSA883X_CHIP_ID3 (WSA883X_DIG_CTRL_BASE + 0x0004) ++#define WSA883X_BUS_ID (WSA883X_DIG_CTRL_BASE + 0x0005) ++#define WSA883X_CDC_RST_CTL (WSA883X_DIG_CTRL_BASE + 0x0006) ++#define WSA883X_TOP_CLK_CFG (WSA883X_DIG_CTRL_BASE + 0x0007) ++#define WSA883X_CDC_PATH_MODE (WSA883X_DIG_CTRL_BASE + 0x0008) ++#define WSA883X_RXD_MODE_MASK BIT(1) ++#define WSA883X_RXD_MODE_NORMAL 0 ++#define WSA883X_RXD_MODE_HIFI 1 ++#define WSA883X_CDC_CLK_CTL (WSA883X_DIG_CTRL_BASE + 0x0009) ++#define WSA883X_SWR_RESET_EN (WSA883X_DIG_CTRL_BASE + 0x000A) ++#define WSA883X_RESET_CTL (WSA883X_DIG_CTRL_BASE + 0x000B) ++#define WSA883X_PA_FSM_CTL (WSA883X_DIG_CTRL_BASE + 0x0010) ++#define WSA883X_GLOBAL_PA_EN_MASK BIT(0) ++#define WSA883X_GLOBAL_PA_ENABLE 1 ++#define WSA883X_PA_FSM_TIMER0 (WSA883X_DIG_CTRL_BASE + 0x0011) ++#define WSA883X_PA_FSM_TIMER1 (WSA883X_DIG_CTRL_BASE + 0x0012) ++#define WSA883X_PA_FSM_STA (WSA883X_DIG_CTRL_BASE + 0x0013) ++#define WSA883X_PA_FSM_ERR_COND (WSA883X_DIG_CTRL_BASE + 0x0014) ++#define WSA883X_PA_FSM_MSK (WSA883X_DIG_CTRL_BASE + 0x0015) ++#define WSA883X_PA_FSM_BYP (WSA883X_DIG_CTRL_BASE + 0x0016) ++#define WSA883X_PA_FSM_DBG (WSA883X_DIG_CTRL_BASE + 0x0017) ++#define WSA883X_TADC_VALUE_CTL (WSA883X_DIG_CTRL_BASE + 0x0020) ++#define WSA883X_TEMP_DETECT_CTL (WSA883X_DIG_CTRL_BASE + 0x0021) ++#define WSA883X_TEMP_MSB (WSA883X_DIG_CTRL_BASE + 0x0022) ++#define WSA883X_TEMP_LSB (WSA883X_DIG_CTRL_BASE + 0x0023) ++#define WSA883X_TEMP_CONFIG0 (WSA883X_DIG_CTRL_BASE + 0x0024) ++#define WSA883X_TEMP_CONFIG1 (WSA883X_DIG_CTRL_BASE + 0x0025) ++#define WSA883X_VBAT_ADC_FLT_CTL (WSA883X_DIG_CTRL_BASE + 0x0026) ++#define WSA883X_VBAT_ADC_FLT_EN_MASK BIT(0) ++#define WSA883X_VBAT_ADC_COEF_SEL_MASK GENMASK(3, 1) ++#define WSA883X_VBAT_ADC_COEF_F_1DIV2 0x0 ++#define WSA883X_VBAT_ADC_COEF_F_1DIV16 0x3 ++#define WSA883X_VBAT_DIN_MSB (WSA883X_DIG_CTRL_BASE + 0x0027) ++#define WSA883X_VBAT_DIN_LSB (WSA883X_DIG_CTRL_BASE + 0x0028) ++#define WSA883X_VBAT_DOUT (WSA883X_DIG_CTRL_BASE + 0x0029) ++#define WSA883X_SDM_PDM9_LSB (WSA883X_DIG_CTRL_BASE + 0x002A) ++#define WSA883X_SDM_PDM9_MSB (WSA883X_DIG_CTRL_BASE + 0x002B) ++#define WSA883X_CDC_RX_CTL (WSA883X_DIG_CTRL_BASE + 0x0030) ++#define WSA883X_CDC_SPK_DSM_A1_0 (WSA883X_DIG_CTRL_BASE + 0x0031) ++#define WSA883X_CDC_SPK_DSM_A1_1 (WSA883X_DIG_CTRL_BASE + 0x0032) ++#define WSA883X_CDC_SPK_DSM_A2_0 (WSA883X_DIG_CTRL_BASE + 0x0033) ++#define WSA883X_CDC_SPK_DSM_A2_1 (WSA883X_DIG_CTRL_BASE + 0x0034) ++#define WSA883X_CDC_SPK_DSM_A3_0 (WSA883X_DIG_CTRL_BASE + 0x0035) ++#define WSA883X_CDC_SPK_DSM_A3_1 (WSA883X_DIG_CTRL_BASE + 0x0036) ++#define WSA883X_CDC_SPK_DSM_A4_0 (WSA883X_DIG_CTRL_BASE + 0x0037) ++#define WSA883X_CDC_SPK_DSM_A4_1 (WSA883X_DIG_CTRL_BASE + 0x0038) ++#define WSA883X_CDC_SPK_DSM_A5_0 (WSA883X_DIG_CTRL_BASE + 0x0039) ++#define WSA883X_CDC_SPK_DSM_A5_1 (WSA883X_DIG_CTRL_BASE + 0x003A) ++#define WSA883X_CDC_SPK_DSM_A6_0 (WSA883X_DIG_CTRL_BASE + 0x003B) ++#define WSA883X_CDC_SPK_DSM_A7_0 (WSA883X_DIG_CTRL_BASE + 0x003C) ++#define WSA883X_CDC_SPK_DSM_C_0 (WSA883X_DIG_CTRL_BASE + 0x003D) ++#define WSA883X_CDC_SPK_DSM_C_1 (WSA883X_DIG_CTRL_BASE + 0x003E) ++#define WSA883X_CDC_SPK_DSM_C_2 (WSA883X_DIG_CTRL_BASE + 0x003F) ++#define WSA883X_CDC_SPK_DSM_C_3 (WSA883X_DIG_CTRL_BASE + 0x0040) ++#define WSA883X_CDC_SPK_DSM_R1 (WSA883X_DIG_CTRL_BASE + 0x0041) ++#define WSA883X_CDC_SPK_DSM_R2 (WSA883X_DIG_CTRL_BASE + 0x0042) ++#define WSA883X_CDC_SPK_DSM_R3 (WSA883X_DIG_CTRL_BASE + 0x0043) ++#define WSA883X_CDC_SPK_DSM_R4 (WSA883X_DIG_CTRL_BASE + 0x0044) ++#define WSA883X_CDC_SPK_DSM_R5 (WSA883X_DIG_CTRL_BASE + 0x0045) ++#define WSA883X_CDC_SPK_DSM_R6 (WSA883X_DIG_CTRL_BASE + 0x0046) ++#define WSA883X_CDC_SPK_DSM_R7 (WSA883X_DIG_CTRL_BASE + 0x0047) ++#define WSA883X_CDC_SPK_GAIN_PDM_0 (WSA883X_DIG_CTRL_BASE + 0x0048) ++#define WSA883X_CDC_SPK_GAIN_PDM_1 (WSA883X_DIG_CTRL_BASE + 0x0049) ++#define WSA883X_CDC_SPK_GAIN_PDM_2 (WSA883X_DIG_CTRL_BASE + 0x004A) ++#define WSA883X_PDM_WD_CTL (WSA883X_DIG_CTRL_BASE + 0x004B) ++#define WSA883X_PDM_EN_MASK BIT(0) ++#define WSA883X_PDM_ENABLE BIT(0) ++#define WSA883X_DEM_BYPASS_DATA0 (WSA883X_DIG_CTRL_BASE + 0x004C) ++#define WSA883X_DEM_BYPASS_DATA1 (WSA883X_DIG_CTRL_BASE + 0x004D) ++#define WSA883X_DEM_BYPASS_DATA2 (WSA883X_DIG_CTRL_BASE + 0x004E) ++#define WSA883X_DEM_BYPASS_DATA3 (WSA883X_DIG_CTRL_BASE + 0x004F) ++#define WSA883X_WAVG_CTL (WSA883X_DIG_CTRL_BASE + 0x0050) ++#define WSA883X_WAVG_LRA_PER_0 (WSA883X_DIG_CTRL_BASE + 0x0051) ++#define WSA883X_WAVG_LRA_PER_1 (WSA883X_DIG_CTRL_BASE + 0x0052) ++#define WSA883X_WAVG_DELTA_THETA_0 (WSA883X_DIG_CTRL_BASE + 0x0053) ++#define WSA883X_WAVG_DELTA_THETA_1 (WSA883X_DIG_CTRL_BASE + 0x0054) ++#define WSA883X_WAVG_DIRECT_AMP_0 (WSA883X_DIG_CTRL_BASE + 0x0055) ++#define WSA883X_WAVG_DIRECT_AMP_1 (WSA883X_DIG_CTRL_BASE + 0x0056) ++#define WSA883X_WAVG_PTRN_AMP0_0 (WSA883X_DIG_CTRL_BASE + 0x0057) ++#define WSA883X_WAVG_PTRN_AMP0_1 (WSA883X_DIG_CTRL_BASE + 0x0058) ++#define WSA883X_WAVG_PTRN_AMP1_0 (WSA883X_DIG_CTRL_BASE + 0x0059) ++#define WSA883X_WAVG_PTRN_AMP1_1 (WSA883X_DIG_CTRL_BASE + 0x005A) ++#define WSA883X_WAVG_PTRN_AMP2_0 (WSA883X_DIG_CTRL_BASE + 0x005B) ++#define WSA883X_WAVG_PTRN_AMP2_1 (WSA883X_DIG_CTRL_BASE + 0x005C) ++#define WSA883X_WAVG_PTRN_AMP3_0 (WSA883X_DIG_CTRL_BASE + 0x005D) ++#define WSA883X_WAVG_PTRN_AMP3_1 (WSA883X_DIG_CTRL_BASE + 0x005E) ++#define WSA883X_WAVG_PTRN_AMP4_0 (WSA883X_DIG_CTRL_BASE + 0x005F) ++#define WSA883X_WAVG_PTRN_AMP4_1 (WSA883X_DIG_CTRL_BASE + 0x0060) ++#define WSA883X_WAVG_PTRN_AMP5_0 (WSA883X_DIG_CTRL_BASE + 0x0061) ++#define WSA883X_WAVG_PTRN_AMP5_1 (WSA883X_DIG_CTRL_BASE + 0x0062) ++#define WSA883X_WAVG_PTRN_AMP6_0 (WSA883X_DIG_CTRL_BASE + 0x0063) ++#define WSA883X_WAVG_PTRN_AMP6_1 (WSA883X_DIG_CTRL_BASE + 0x0064) ++#define WSA883X_WAVG_PTRN_AMP7_0 (WSA883X_DIG_CTRL_BASE + 0x0065) ++#define WSA883X_WAVG_PTRN_AMP7_1 (WSA883X_DIG_CTRL_BASE + 0x0066) ++#define WSA883X_WAVG_PER_0_1 (WSA883X_DIG_CTRL_BASE + 0x0067) ++#define WSA883X_WAVG_PER_2_3 (WSA883X_DIG_CTRL_BASE + 0x0068) ++#define WSA883X_WAVG_PER_4_5 (WSA883X_DIG_CTRL_BASE + 0x0069) ++#define WSA883X_WAVG_PER_6_7 (WSA883X_DIG_CTRL_BASE + 0x006A) ++#define WSA883X_WAVG_STA (WSA883X_DIG_CTRL_BASE + 0x006B) ++#define WSA883X_DRE_CTL_0 (WSA883X_DIG_CTRL_BASE + 0x006C) ++#define WSA883X_DRE_OFFSET_MASK GENMASK(2, 0) ++#define WSA883X_DRE_PROG_DELAY_MASK GENMASK(7, 4) ++#define WSA883X_DRE_CTL_1 (WSA883X_DIG_CTRL_BASE + 0x006D) ++#define WSA883X_DRE_GAIN_EN_MASK BIT(0) ++#define WSA883X_DRE_GAIN_FROM_CSR 1 ++#define WSA883X_DRE_IDLE_DET_CTL (WSA883X_DIG_CTRL_BASE + 0x006E) ++#define WSA883X_CLSH_CTL_0 (WSA883X_DIG_CTRL_BASE + 0x0070) ++#define WSA883X_CLSH_CTL_1 (WSA883X_DIG_CTRL_BASE + 0x0071) ++#define WSA883X_CLSH_V_HD_PA (WSA883X_DIG_CTRL_BASE + 0x0072) ++#define WSA883X_CLSH_V_PA_MIN (WSA883X_DIG_CTRL_BASE + 0x0073) ++#define WSA883X_CLSH_OVRD_VAL (WSA883X_DIG_CTRL_BASE + 0x0074) ++#define WSA883X_CLSH_HARD_MAX (WSA883X_DIG_CTRL_BASE + 0x0075) ++#define WSA883X_CLSH_SOFT_MAX (WSA883X_DIG_CTRL_BASE + 0x0076) ++#define WSA883X_CLSH_SIG_DP (WSA883X_DIG_CTRL_BASE + 0x0077) ++#define WSA883X_TAGC_CTL (WSA883X_DIG_CTRL_BASE + 0x0078) ++#define WSA883X_TAGC_TIME (WSA883X_DIG_CTRL_BASE + 0x0079) ++#define WSA883X_TAGC_E2E_GAIN (WSA883X_DIG_CTRL_BASE + 0x007A) ++#define WSA883X_TAGC_FORCE_VAL (WSA883X_DIG_CTRL_BASE + 0x007B) ++#define WSA883X_VAGC_CTL (WSA883X_DIG_CTRL_BASE + 0x007C) ++#define WSA883X_VAGC_TIME (WSA883X_DIG_CTRL_BASE + 0x007D) ++#define WSA883X_VAGC_ATTN_LVL_1_2 (WSA883X_DIG_CTRL_BASE + 0x007E) ++#define WSA883X_VAGC_ATTN_LVL_3 (WSA883X_DIG_CTRL_BASE + 0x007F) ++#define WSA883X_INTR_MODE (WSA883X_DIG_CTRL_BASE + 0x0080) ++#define WSA883X_INTR_MASK0 (WSA883X_DIG_CTRL_BASE + 0x0081) ++#define WSA883X_INTR_MASK1 (WSA883X_DIG_CTRL_BASE + 0x0082) ++#define WSA883X_INTR_STATUS0 (WSA883X_DIG_CTRL_BASE + 0x0083) ++#define WSA883X_INTR_STATUS1 (WSA883X_DIG_CTRL_BASE + 0x0084) ++#define WSA883X_INTR_CLEAR0 (WSA883X_DIG_CTRL_BASE + 0x0085) ++#define WSA883X_INTR_CLEAR1 (WSA883X_DIG_CTRL_BASE + 0x0086) ++#define WSA883X_INTR_LEVEL0 (WSA883X_DIG_CTRL_BASE + 0x0087) ++#define WSA883X_INTR_LEVEL1 (WSA883X_DIG_CTRL_BASE + 0x0088) ++#define WSA883X_INTR_SET0 (WSA883X_DIG_CTRL_BASE + 0x0089) ++#define WSA883X_INTR_SET1 (WSA883X_DIG_CTRL_BASE + 0x008A) ++#define WSA883X_INTR_TEST0 (WSA883X_DIG_CTRL_BASE + 0x008B) ++#define WSA883X_INTR_TEST1 (WSA883X_DIG_CTRL_BASE + 0x008C) ++#define WSA883X_OTP_CTRL0 (WSA883X_DIG_CTRL_BASE + 0x0090) ++#define WSA883X_OTP_CTRL1 (WSA883X_DIG_CTRL_BASE + 0x0091) ++#define WSA883X_HDRIVE_CTL_GROUP1 (WSA883X_DIG_CTRL_BASE + 0x0092) ++#define WSA883X_PIN_CTL (WSA883X_DIG_CTRL_BASE + 0x0093) ++#define WSA883X_PIN_CTL_OE (WSA883X_DIG_CTRL_BASE + 0x0094) ++#define WSA883X_PIN_WDATA_IOPAD (WSA883X_DIG_CTRL_BASE + 0x0095) ++#define WSA883X_PIN_STATUS (WSA883X_DIG_CTRL_BASE + 0x0096) ++#define WSA883X_I2C_SLAVE_CTL (WSA883X_DIG_CTRL_BASE + 0x0097) ++#define WSA883X_PDM_TEST_MODE (WSA883X_DIG_CTRL_BASE + 0x00A0) ++#define WSA883X_ATE_TEST_MODE (WSA883X_DIG_CTRL_BASE + 0x00A1) ++#define WSA883X_DIG_DEBUG_MODE (WSA883X_DIG_CTRL_BASE + 0x00A3) ++#define WSA883X_DIG_DEBUG_SEL (WSA883X_DIG_CTRL_BASE + 0x00A4) ++#define WSA883X_DIG_DEBUG_EN (WSA883X_DIG_CTRL_BASE + 0x00A5) ++#define WSA883X_SWR_HM_TEST0 (WSA883X_DIG_CTRL_BASE + 0x00A6) ++#define WSA883X_SWR_HM_TEST1 (WSA883X_DIG_CTRL_BASE + 0x00A7) ++#define WSA883X_SWR_PAD_CTL (WSA883X_DIG_CTRL_BASE + 0x00A8) ++#define WSA883X_TADC_DETECT_DBG_CTL (WSA883X_DIG_CTRL_BASE + 0x00A9) ++#define WSA883X_TADC_DEBUG_MSB (WSA883X_DIG_CTRL_BASE + 0x00AA) ++#define WSA883X_TADC_DEBUG_LSB (WSA883X_DIG_CTRL_BASE + 0x00AB) ++#define WSA883X_SAMPLE_EDGE_SEL (WSA883X_DIG_CTRL_BASE + 0x00AC) ++#define WSA883X_SWR_EDGE_SEL (WSA883X_DIG_CTRL_BASE + 0x00AD) ++#define WSA883X_TEST_MODE_CTL (WSA883X_DIG_CTRL_BASE + 0x00AE) ++#define WSA883X_IOPAD_CTL (WSA883X_DIG_CTRL_BASE + 0x00AF) ++#define WSA883X_ANA_CSR_DBG_ADD (WSA883X_DIG_CTRL_BASE + 0x00B0) ++#define WSA883X_ANA_CSR_DBG_CTL (WSA883X_DIG_CTRL_BASE + 0x00B1) ++#define WSA883X_SPARE_R (WSA883X_DIG_CTRL_BASE + 0x00BC) ++#define WSA883X_SPARE_0 (WSA883X_DIG_CTRL_BASE + 0x00BD) ++#define WSA883X_SPARE_1 (WSA883X_DIG_CTRL_BASE + 0x00BE) ++#define WSA883X_SPARE_2 (WSA883X_DIG_CTRL_BASE + 0x00BF) ++#define WSA883X_SCODE (WSA883X_DIG_CTRL_BASE + 0x00C0) ++ ++#define WSA883X_DIG_TRIM_BASE (WSA883X_BASE + 0x00000500) ++#define WSA883X_OTP_REG_0 (WSA883X_DIG_TRIM_BASE + 0x0080) ++#define WSA883X_ID_MASK GENMASK(3, 0) ++#define WSA883X_OTP_REG_1 (WSA883X_DIG_TRIM_BASE + 0x0081) ++#define WSA883X_OTP_REG_2 (WSA883X_DIG_TRIM_BASE + 0x0082) ++#define WSA883X_OTP_REG_3 (WSA883X_DIG_TRIM_BASE + 0x0083) ++#define WSA883X_OTP_REG_4 (WSA883X_DIG_TRIM_BASE + 0x0084) ++#define WSA883X_OTP_REG_5 (WSA883X_DIG_TRIM_BASE + 0x0085) ++#define WSA883X_OTP_REG_6 (WSA883X_DIG_TRIM_BASE + 0x0086) ++#define WSA883X_OTP_REG_7 (WSA883X_DIG_TRIM_BASE + 0x0087) ++#define WSA883X_OTP_REG_8 (WSA883X_DIG_TRIM_BASE + 0x0088) ++#define WSA883X_OTP_REG_9 (WSA883X_DIG_TRIM_BASE + 0x0089) ++#define WSA883X_OTP_REG_10 (WSA883X_DIG_TRIM_BASE + 0x008A) ++#define WSA883X_OTP_REG_11 (WSA883X_DIG_TRIM_BASE + 0x008B) ++#define WSA883X_OTP_REG_12 (WSA883X_DIG_TRIM_BASE + 0x008C) ++#define WSA883X_OTP_REG_13 (WSA883X_DIG_TRIM_BASE + 0x008D) ++#define WSA883X_OTP_REG_14 (WSA883X_DIG_TRIM_BASE + 0x008E) ++#define WSA883X_OTP_REG_15 (WSA883X_DIG_TRIM_BASE + 0x008F) ++#define WSA883X_OTP_REG_16 (WSA883X_DIG_TRIM_BASE + 0x0090) ++#define WSA883X_OTP_REG_17 (WSA883X_DIG_TRIM_BASE + 0x0091) ++#define WSA883X_OTP_REG_18 (WSA883X_DIG_TRIM_BASE + 0x0092) ++#define WSA883X_OTP_REG_19 (WSA883X_DIG_TRIM_BASE + 0x0093) ++#define WSA883X_OTP_REG_20 (WSA883X_DIG_TRIM_BASE + 0x0094) ++#define WSA883X_OTP_REG_21 (WSA883X_DIG_TRIM_BASE + 0x0095) ++#define WSA883X_OTP_REG_22 (WSA883X_DIG_TRIM_BASE + 0x0096) ++#define WSA883X_OTP_REG_23 (WSA883X_DIG_TRIM_BASE + 0x0097) ++#define WSA883X_OTP_REG_24 (WSA883X_DIG_TRIM_BASE + 0x0098) ++#define WSA883X_OTP_REG_25 (WSA883X_DIG_TRIM_BASE + 0x0099) ++#define WSA883X_OTP_REG_26 (WSA883X_DIG_TRIM_BASE + 0x009A) ++#define WSA883X_OTP_REG_27 (WSA883X_DIG_TRIM_BASE + 0x009B) ++#define WSA883X_OTP_REG_28 (WSA883X_DIG_TRIM_BASE + 0x009C) ++#define WSA883X_OTP_REG_29 (WSA883X_DIG_TRIM_BASE + 0x009D) ++#define WSA883X_OTP_REG_30 (WSA883X_DIG_TRIM_BASE + 0x009E) ++#define WSA883X_OTP_REG_31 (WSA883X_DIG_TRIM_BASE + 0x009F) ++#define WSA883X_OTP_REG_32 (WSA883X_DIG_TRIM_BASE + 0x00A0) ++#define WSA883X_OTP_REG_33 (WSA883X_DIG_TRIM_BASE + 0x00A1) ++#define WSA883X_OTP_REG_34 (WSA883X_DIG_TRIM_BASE + 0x00A2) ++#define WSA883X_OTP_REG_35 (WSA883X_DIG_TRIM_BASE + 0x00A3) ++#define WSA883X_OTP_REG_63 (WSA883X_DIG_TRIM_BASE + 0x00BF) ++ ++#define WSA883X_DIG_EMEM_BASE (WSA883X_BASE + 0x000005C0) ++#define WSA883X_EMEM_0 (WSA883X_DIG_EMEM_BASE + 0x0000) ++#define WSA883X_EMEM_1 (WSA883X_DIG_EMEM_BASE + 0x0001) ++#define WSA883X_EMEM_2 (WSA883X_DIG_EMEM_BASE + 0x0002) ++#define WSA883X_EMEM_3 (WSA883X_DIG_EMEM_BASE + 0x0003) ++#define WSA883X_EMEM_4 (WSA883X_DIG_EMEM_BASE + 0x0004) ++#define WSA883X_EMEM_5 (WSA883X_DIG_EMEM_BASE + 0x0005) ++#define WSA883X_EMEM_6 (WSA883X_DIG_EMEM_BASE + 0x0006) ++#define WSA883X_EMEM_7 (WSA883X_DIG_EMEM_BASE + 0x0007) ++#define WSA883X_EMEM_8 (WSA883X_DIG_EMEM_BASE + 0x0008) ++#define WSA883X_EMEM_9 (WSA883X_DIG_EMEM_BASE + 0x0009) ++#define WSA883X_EMEM_10 (WSA883X_DIG_EMEM_BASE + 0x000A) ++#define WSA883X_EMEM_11 (WSA883X_DIG_EMEM_BASE + 0x000B) ++#define WSA883X_EMEM_12 (WSA883X_DIG_EMEM_BASE + 0x000C) ++#define WSA883X_EMEM_13 (WSA883X_DIG_EMEM_BASE + 0x000D) ++#define WSA883X_EMEM_14 (WSA883X_DIG_EMEM_BASE + 0x000E) ++#define WSA883X_EMEM_15 (WSA883X_DIG_EMEM_BASE + 0x000F) ++#define WSA883X_EMEM_16 (WSA883X_DIG_EMEM_BASE + 0x0010) ++#define WSA883X_EMEM_17 (WSA883X_DIG_EMEM_BASE + 0x0011) ++#define WSA883X_EMEM_18 (WSA883X_DIG_EMEM_BASE + 0x0012) ++#define WSA883X_EMEM_19 (WSA883X_DIG_EMEM_BASE + 0x0013) ++#define WSA883X_EMEM_20 (WSA883X_DIG_EMEM_BASE + 0x0014) ++#define WSA883X_EMEM_21 (WSA883X_DIG_EMEM_BASE + 0x0015) ++#define WSA883X_EMEM_22 (WSA883X_DIG_EMEM_BASE + 0x0016) ++#define WSA883X_EMEM_23 (WSA883X_DIG_EMEM_BASE + 0x0017) ++#define WSA883X_EMEM_24 (WSA883X_DIG_EMEM_BASE + 0x0018) ++#define WSA883X_EMEM_25 (WSA883X_DIG_EMEM_BASE + 0x0019) ++#define WSA883X_EMEM_26 (WSA883X_DIG_EMEM_BASE + 0x001A) ++#define WSA883X_EMEM_27 (WSA883X_DIG_EMEM_BASE + 0x001B) ++#define WSA883X_EMEM_28 (WSA883X_DIG_EMEM_BASE + 0x001C) ++#define WSA883X_EMEM_29 (WSA883X_DIG_EMEM_BASE + 0x001D) ++#define WSA883X_EMEM_30 (WSA883X_DIG_EMEM_BASE + 0x001E) ++#define WSA883X_EMEM_31 (WSA883X_DIG_EMEM_BASE + 0x001F) ++#define WSA883X_EMEM_32 (WSA883X_DIG_EMEM_BASE + 0x0020) ++#define WSA883X_EMEM_33 (WSA883X_DIG_EMEM_BASE + 0x0021) ++#define WSA883X_EMEM_34 (WSA883X_DIG_EMEM_BASE + 0x0022) ++#define WSA883X_EMEM_35 (WSA883X_DIG_EMEM_BASE + 0x0023) ++#define WSA883X_EMEM_36 (WSA883X_DIG_EMEM_BASE + 0x0024) ++#define WSA883X_EMEM_37 (WSA883X_DIG_EMEM_BASE + 0x0025) ++#define WSA883X_EMEM_38 (WSA883X_DIG_EMEM_BASE + 0x0026) ++#define WSA883X_EMEM_39 (WSA883X_DIG_EMEM_BASE + 0x0027) ++#define WSA883X_EMEM_40 (WSA883X_DIG_EMEM_BASE + 0x0028) ++#define WSA883X_EMEM_41 (WSA883X_DIG_EMEM_BASE + 0x0029) ++#define WSA883X_EMEM_42 (WSA883X_DIG_EMEM_BASE + 0x002A) ++#define WSA883X_EMEM_43 (WSA883X_DIG_EMEM_BASE + 0x002B) ++#define WSA883X_EMEM_44 (WSA883X_DIG_EMEM_BASE + 0x002C) ++#define WSA883X_EMEM_45 (WSA883X_DIG_EMEM_BASE + 0x002D) ++#define WSA883X_EMEM_46 (WSA883X_DIG_EMEM_BASE + 0x002E) ++#define WSA883X_EMEM_47 (WSA883X_DIG_EMEM_BASE + 0x002F) ++#define WSA883X_EMEM_48 (WSA883X_DIG_EMEM_BASE + 0x0030) ++#define WSA883X_EMEM_49 (WSA883X_DIG_EMEM_BASE + 0x0031) ++#define WSA883X_EMEM_50 (WSA883X_DIG_EMEM_BASE + 0x0032) ++#define WSA883X_EMEM_51 (WSA883X_DIG_EMEM_BASE + 0x0033) ++#define WSA883X_EMEM_52 (WSA883X_DIG_EMEM_BASE + 0x0034) ++#define WSA883X_EMEM_53 (WSA883X_DIG_EMEM_BASE + 0x0035) ++#define WSA883X_EMEM_54 (WSA883X_DIG_EMEM_BASE + 0x0036) ++#define WSA883X_EMEM_55 (WSA883X_DIG_EMEM_BASE + 0x0037) ++#define WSA883X_EMEM_56 (WSA883X_DIG_EMEM_BASE + 0x0038) ++#define WSA883X_EMEM_57 (WSA883X_DIG_EMEM_BASE + 0x0039) ++#define WSA883X_EMEM_58 (WSA883X_DIG_EMEM_BASE + 0x003A) ++#define WSA883X_EMEM_59 (WSA883X_DIG_EMEM_BASE + 0x003B) ++#define WSA883X_EMEM_60 (WSA883X_DIG_EMEM_BASE + 0x003C) ++#define WSA883X_EMEM_61 (WSA883X_DIG_EMEM_BASE + 0x003D) ++#define WSA883X_EMEM_62 (WSA883X_DIG_EMEM_BASE + 0x003E) ++#define WSA883X_EMEM_63 (WSA883X_DIG_EMEM_BASE + 0x003F) ++ ++#define WSA883X_NUM_REGISTERS (WSA883X_EMEM_63 + 1) ++#define WSA883X_MAX_REGISTER (WSA883X_NUM_REGISTERS - 1) ++#define WSA883X_PROBE_TIMEOUT 1000 ++ ++#define WSA883X_VERSION_1_0 0 ++#define WSA883X_VERSION_1_1 1 ++ ++#define WSA883X_MAX_SWR_PORTS 4 ++#define WSA883X_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 |\ ++ SNDRV_PCM_RATE_384000) ++/* Fractional Rates */ ++#define WSA883X_FRAC_RATES (SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_88200 |\ ++ SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_352800) ++ ++#define WSA883X_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\ ++ SNDRV_PCM_FMTBIT_S24_LE |\ ++ SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S32_LE) ++ ++struct wsa883x_priv { ++ struct regmap *regmap; ++ struct device *dev; ++ struct regulator *vdd; ++ struct sdw_slave *slave; ++ struct sdw_stream_config sconfig; ++ struct sdw_stream_runtime *sruntime; ++ struct sdw_port_config port_config[WSA883X_MAX_SWR_PORTS]; ++ struct gpio_desc *sd_n; ++ bool port_prepared[WSA883X_MAX_SWR_PORTS]; ++ bool port_enable[WSA883X_MAX_SWR_PORTS]; ++ int version; ++ int variant; ++ int active_ports; ++ int dev_mode; ++ int comp_offset; ++}; ++ ++enum { ++ WSA8830 = 0, ++ WSA8835, ++ WSA8832, ++ WSA8835_V2 = 5, ++}; ++ ++enum { ++ COMP_OFFSET0, ++ COMP_OFFSET1, ++ COMP_OFFSET2, ++ COMP_OFFSET3, ++ COMP_OFFSET4, ++}; ++ ++enum wsa_port_ids { ++ WSA883X_PORT_DAC, ++ WSA883X_PORT_COMP, ++ WSA883X_PORT_BOOST, ++ WSA883X_PORT_VISENSE, ++}; ++ ++/* 4 ports */ ++static struct sdw_dpn_prop wsa_sink_dpn_prop[WSA883X_MAX_SWR_PORTS] = { ++ { ++ /* DAC */ ++ .num = 1, ++ .type = SDW_DPN_SIMPLE, ++ .min_ch = 1, ++ .max_ch = 1, ++ .simple_ch_prep_sm = true, ++ .read_only_wordlength = true, ++ }, { ++ /* COMP */ ++ .num = 2, ++ .type = SDW_DPN_SIMPLE, ++ .min_ch = 1, ++ .max_ch = 1, ++ .simple_ch_prep_sm = true, ++ .read_only_wordlength = true, ++ }, { ++ /* BOOST */ ++ .num = 3, ++ .type = SDW_DPN_SIMPLE, ++ .min_ch = 1, ++ .max_ch = 1, ++ .simple_ch_prep_sm = true, ++ .read_only_wordlength = true, ++ }, { ++ /* VISENSE */ ++ .num = 4, ++ .type = SDW_DPN_SIMPLE, ++ .min_ch = 1, ++ .max_ch = 1, ++ .simple_ch_prep_sm = true, ++ .read_only_wordlength = true, ++ } ++}; ++ ++static struct sdw_port_config wsa883x_pconfig[WSA883X_MAX_SWR_PORTS] = { ++ { ++ .num = 1, ++ .ch_mask = 0x1, ++ }, { ++ .num = 2, ++ .ch_mask = 0xf, ++ }, { ++ .num = 3, ++ .ch_mask = 0x3, ++ }, { /* IV feedback */ ++ .num = 4, ++ .ch_mask = 0x3, ++ }, ++}; ++ ++static struct reg_default wsa883x_defaults[] = { ++ { WSA883X_REF_CTRL, 0xD5 }, ++ { WSA883X_TEST_CTL_0, 0x06 }, ++ { WSA883X_BIAS_0, 0xD2 }, ++ { WSA883X_OP_CTL, 0xE0 }, ++ { WSA883X_IREF_CTL, 0x57 }, ++ { WSA883X_ISENS_CTL, 0x47 }, ++ { WSA883X_CLK_CTL, 0x87 }, ++ { WSA883X_TEST_CTL_1, 0x00 }, ++ { WSA883X_BIAS_1, 0x51 }, ++ { WSA883X_ADC_CTL, 0x01 }, ++ { WSA883X_DOUT_MSB, 0x00 }, ++ { WSA883X_DOUT_LSB, 0x00 }, ++ { WSA883X_VBAT_SNS, 0x40 }, ++ { WSA883X_ITRIM_CODE, 0x9F }, ++ { WSA883X_EN, 0x20 }, ++ { WSA883X_OVERRIDE1, 0x00 }, ++ { WSA883X_OVERRIDE2, 0x08 }, ++ { WSA883X_VSENSE1, 0xD3 }, ++ { WSA883X_ISENSE1, 0xD4 }, ++ { WSA883X_ISENSE2, 0x20 }, ++ { WSA883X_ISENSE_CAL, 0x00 }, ++ { WSA883X_MISC, 0x08 }, ++ { WSA883X_ADC_0, 0x00 }, ++ { WSA883X_ADC_1, 0x00 }, ++ { WSA883X_ADC_2, 0x40 }, ++ { WSA883X_ADC_3, 0x80 }, ++ { WSA883X_ADC_4, 0x25 }, ++ { WSA883X_ADC_5, 0x25 }, ++ { WSA883X_ADC_6, 0x08 }, ++ { WSA883X_ADC_7, 0x81 }, ++ { WSA883X_STATUS, 0x00 }, ++ { WSA883X_DAC_CTRL_REG, 0x53 }, ++ { WSA883X_DAC_EN_DEBUG_REG, 0x00 }, ++ { WSA883X_DAC_OPAMP_BIAS1_REG, 0x48 }, ++ { WSA883X_DAC_OPAMP_BIAS2_REG, 0x48 }, ++ { WSA883X_DAC_VCM_CTRL_REG, 0x88 }, ++ { WSA883X_DAC_VOLTAGE_CTRL_REG, 0xA5 }, ++ { WSA883X_ATEST1_REG, 0x00 }, ++ { WSA883X_ATEST2_REG, 0x00 }, ++ { WSA883X_SPKR_TOP_BIAS_REG1, 0x6A }, ++ { WSA883X_SPKR_TOP_BIAS_REG2, 0x65 }, ++ { WSA883X_SPKR_TOP_BIAS_REG3, 0x55 }, ++ { WSA883X_SPKR_TOP_BIAS_REG4, 0xA9 }, ++ { WSA883X_SPKR_CLIP_DET_REG, 0x9C }, ++ { WSA883X_SPKR_DRV_LF_BLK_EN, 0x0F }, ++ { WSA883X_SPKR_DRV_LF_EN, 0x0A }, ++ { WSA883X_SPKR_DRV_LF_MASK_DCC_CTL, 0x00 }, ++ { WSA883X_SPKR_DRV_LF_MISC_CTL, 0x3A }, ++ { WSA883X_SPKR_DRV_LF_REG_GAIN, 0x00 }, ++ { WSA883X_SPKR_DRV_OS_CAL_CTL, 0x00 }, ++ { WSA883X_SPKR_DRV_OS_CAL_CTL1, 0x90 }, ++ { WSA883X_SPKR_PWM_CLK_CTL, 0x00 }, ++ { WSA883X_SPKR_PDRV_HS_CTL, 0x52 }, ++ { WSA883X_SPKR_PDRV_LS_CTL, 0x48 }, ++ { WSA883X_SPKR_PWRSTG_DBG, 0x08 }, ++ { WSA883X_SPKR_OCP_CTL, 0xE2 }, ++ { WSA883X_SPKR_BBM_CTL, 0x92 }, ++ { WSA883X_PA_STATUS0, 0x00 }, ++ { WSA883X_PA_STATUS1, 0x00 }, ++ { WSA883X_PA_STATUS2, 0x80 }, ++ { WSA883X_EN_CTRL, 0x44 }, ++ { WSA883X_CURRENT_LIMIT, 0xCC }, ++ { WSA883X_IBIAS1, 0x00 }, ++ { WSA883X_IBIAS2, 0x00 }, ++ { WSA883X_IBIAS3, 0x00 }, ++ { WSA883X_LDO_PROG, 0x02 }, ++ { WSA883X_STABILITY_CTRL1, 0x8E }, ++ { WSA883X_STABILITY_CTRL2, 0x10 }, ++ { WSA883X_PWRSTAGE_CTRL1, 0x06 }, ++ { WSA883X_PWRSTAGE_CTRL2, 0x00 }, ++ { WSA883X_BYPASS_1, 0x19 }, ++ { WSA883X_BYPASS_2, 0x13 }, ++ { WSA883X_ZX_CTRL_1, 0xF0 }, ++ { WSA883X_ZX_CTRL_2, 0x04 }, ++ { WSA883X_MISC1, 0x06 }, ++ { WSA883X_MISC2, 0xA0 }, ++ { WSA883X_GMAMP_SUP1, 0x82 }, ++ { WSA883X_PWRSTAGE_CTRL3, 0x39 }, ++ { WSA883X_PWRSTAGE_CTRL4, 0x5F }, ++ { WSA883X_TEST1, 0x00 }, ++ { WSA883X_SPARE1, 0x00 }, ++ { WSA883X_SPARE2, 0x00 }, ++ { WSA883X_PON_CTL_0, 0x10 }, ++ { WSA883X_PON_CLT_1, 0xE0 }, ++ { WSA883X_PON_CTL_2, 0x90 }, ++ { WSA883X_PON_CTL_3, 0x70 }, ++ { WSA883X_CKWD_CTL_0, 0x34 }, ++ { WSA883X_CKWD_CTL_1, 0x0F }, ++ { WSA883X_CKWD_CTL_2, 0x00 }, ++ { WSA883X_CKSK_CTL_0, 0x00 }, ++ { WSA883X_PADSW_CTL_0, 0x00 }, ++ { WSA883X_TEST_0, 0x00 }, ++ { WSA883X_TEST_1, 0x00 }, ++ { WSA883X_STATUS_0, 0x00 }, ++ { WSA883X_STATUS_1, 0x00 }, ++ { WSA883X_CHIP_ID0, 0x00 }, ++ { WSA883X_CHIP_ID1, 0x00 }, ++ { WSA883X_CHIP_ID2, 0x02 }, ++ { WSA883X_CHIP_ID3, 0x02 }, ++ { WSA883X_BUS_ID, 0x00 }, ++ { WSA883X_CDC_RST_CTL, 0x01 }, ++ { WSA883X_TOP_CLK_CFG, 0x00 }, ++ { WSA883X_CDC_PATH_MODE, 0x00 }, ++ { WSA883X_CDC_CLK_CTL, 0xFF }, ++ { WSA883X_SWR_RESET_EN, 0x00 }, ++ { WSA883X_RESET_CTL, 0x00 }, ++ { WSA883X_PA_FSM_CTL, 0x00 }, ++ { WSA883X_PA_FSM_TIMER0, 0x80 }, ++ { WSA883X_PA_FSM_TIMER1, 0x80 }, ++ { WSA883X_PA_FSM_STA, 0x00 }, ++ { WSA883X_PA_FSM_ERR_COND, 0x00 }, ++ { WSA883X_PA_FSM_MSK, 0x00 }, ++ { WSA883X_PA_FSM_BYP, 0x01 }, ++ { WSA883X_PA_FSM_DBG, 0x00 }, ++ { WSA883X_TADC_VALUE_CTL, 0x03 }, ++ { WSA883X_TEMP_DETECT_CTL, 0x01 }, ++ { WSA883X_TEMP_MSB, 0x00 }, ++ { WSA883X_TEMP_LSB, 0x00 }, ++ { WSA883X_TEMP_CONFIG0, 0x00 }, ++ { WSA883X_TEMP_CONFIG1, 0x00 }, ++ { WSA883X_VBAT_ADC_FLT_CTL, 0x00 }, ++ { WSA883X_VBAT_DIN_MSB, 0x00 }, ++ { WSA883X_VBAT_DIN_LSB, 0x00 }, ++ { WSA883X_VBAT_DOUT, 0x00 }, ++ { WSA883X_SDM_PDM9_LSB, 0x00 }, ++ { WSA883X_SDM_PDM9_MSB, 0x00 }, ++ { WSA883X_CDC_RX_CTL, 0xFE }, ++ { WSA883X_CDC_SPK_DSM_A1_0, 0x00 }, ++ { WSA883X_CDC_SPK_DSM_A1_1, 0x01 }, ++ { WSA883X_CDC_SPK_DSM_A2_0, 0x96 }, ++ { WSA883X_CDC_SPK_DSM_A2_1, 0x09 }, ++ { WSA883X_CDC_SPK_DSM_A3_0, 0xAB }, ++ { WSA883X_CDC_SPK_DSM_A3_1, 0x05 }, ++ { WSA883X_CDC_SPK_DSM_A4_0, 0x1C }, ++ { WSA883X_CDC_SPK_DSM_A4_1, 0x02 }, ++ { WSA883X_CDC_SPK_DSM_A5_0, 0x17 }, ++ { WSA883X_CDC_SPK_DSM_A5_1, 0x02 }, ++ { WSA883X_CDC_SPK_DSM_A6_0, 0xAA }, ++ { WSA883X_CDC_SPK_DSM_A7_0, 0xE3 }, ++ { WSA883X_CDC_SPK_DSM_C_0, 0x69 }, ++ { WSA883X_CDC_SPK_DSM_C_1, 0x54 }, ++ { WSA883X_CDC_SPK_DSM_C_2, 0x02 }, ++ { WSA883X_CDC_SPK_DSM_C_3, 0x15 }, ++ { WSA883X_CDC_SPK_DSM_R1, 0xA4 }, ++ { WSA883X_CDC_SPK_DSM_R2, 0xB5 }, ++ { WSA883X_CDC_SPK_DSM_R3, 0x86 }, ++ { WSA883X_CDC_SPK_DSM_R4, 0x85 }, ++ { WSA883X_CDC_SPK_DSM_R5, 0xAA }, ++ { WSA883X_CDC_SPK_DSM_R6, 0xE2 }, ++ { WSA883X_CDC_SPK_DSM_R7, 0x62 }, ++ { WSA883X_CDC_SPK_GAIN_PDM_0, 0x00 }, ++ { WSA883X_CDC_SPK_GAIN_PDM_1, 0xFC }, ++ { WSA883X_CDC_SPK_GAIN_PDM_2, 0x05 }, ++ { WSA883X_PDM_WD_CTL, 0x00 }, ++ { WSA883X_DEM_BYPASS_DATA0, 0x00 }, ++ { WSA883X_DEM_BYPASS_DATA1, 0x00 }, ++ { WSA883X_DEM_BYPASS_DATA2, 0x00 }, ++ { WSA883X_DEM_BYPASS_DATA3, 0x00 }, ++ { WSA883X_WAVG_CTL, 0x06 }, ++ { WSA883X_WAVG_LRA_PER_0, 0xD1 }, ++ { WSA883X_WAVG_LRA_PER_1, 0x00 }, ++ { WSA883X_WAVG_DELTA_THETA_0, 0xE6 }, ++ { WSA883X_WAVG_DELTA_THETA_1, 0x04 }, ++ { WSA883X_WAVG_DIRECT_AMP_0, 0x50 }, ++ { WSA883X_WAVG_DIRECT_AMP_1, 0x00 }, ++ { WSA883X_WAVG_PTRN_AMP0_0, 0x50 }, ++ { WSA883X_WAVG_PTRN_AMP0_1, 0x00 }, ++ { WSA883X_WAVG_PTRN_AMP1_0, 0x50 }, ++ { WSA883X_WAVG_PTRN_AMP1_1, 0x00 }, ++ { WSA883X_WAVG_PTRN_AMP2_0, 0x50 }, ++ { WSA883X_WAVG_PTRN_AMP2_1, 0x00 }, ++ { WSA883X_WAVG_PTRN_AMP3_0, 0x50 }, ++ { WSA883X_WAVG_PTRN_AMP3_1, 0x00 }, ++ { WSA883X_WAVG_PTRN_AMP4_0, 0x50 }, ++ { WSA883X_WAVG_PTRN_AMP4_1, 0x00 }, ++ { WSA883X_WAVG_PTRN_AMP5_0, 0x50 }, ++ { WSA883X_WAVG_PTRN_AMP5_1, 0x00 }, ++ { WSA883X_WAVG_PTRN_AMP6_0, 0x50 }, ++ { WSA883X_WAVG_PTRN_AMP6_1, 0x00 }, ++ { WSA883X_WAVG_PTRN_AMP7_0, 0x50 }, ++ { WSA883X_WAVG_PTRN_AMP7_1, 0x00 }, ++ { WSA883X_WAVG_PER_0_1, 0x88 }, ++ { WSA883X_WAVG_PER_2_3, 0x88 }, ++ { WSA883X_WAVG_PER_4_5, 0x88 }, ++ { WSA883X_WAVG_PER_6_7, 0x88 }, ++ { WSA883X_WAVG_STA, 0x00 }, ++ { WSA883X_DRE_CTL_0, 0x70 }, ++ { WSA883X_DRE_CTL_1, 0x08 }, ++ { WSA883X_DRE_IDLE_DET_CTL, 0x1F }, ++ { WSA883X_CLSH_CTL_0, 0x37 }, ++ { WSA883X_CLSH_CTL_1, 0x81 }, ++ { WSA883X_CLSH_V_HD_PA, 0x0F }, ++ { WSA883X_CLSH_V_PA_MIN, 0x00 }, ++ { WSA883X_CLSH_OVRD_VAL, 0x00 }, ++ { WSA883X_CLSH_HARD_MAX, 0xFF }, ++ { WSA883X_CLSH_SOFT_MAX, 0xF5 }, ++ { WSA883X_CLSH_SIG_DP, 0x00 }, ++ { WSA883X_TAGC_CTL, 0x10 }, ++ { WSA883X_TAGC_TIME, 0x20 }, ++ { WSA883X_TAGC_E2E_GAIN, 0x02 }, ++ { WSA883X_TAGC_FORCE_VAL, 0x00 }, ++ { WSA883X_VAGC_CTL, 0x00 }, ++ { WSA883X_VAGC_TIME, 0x08 }, ++ { WSA883X_VAGC_ATTN_LVL_1_2, 0x21 }, ++ { WSA883X_VAGC_ATTN_LVL_3, 0x03 }, ++ { WSA883X_INTR_MODE, 0x00 }, ++ { WSA883X_INTR_MASK0, 0x90 }, ++ { WSA883X_INTR_MASK1, 0x00 }, ++ { WSA883X_INTR_STATUS0, 0x00 }, ++ { WSA883X_INTR_STATUS1, 0x00 }, ++ { WSA883X_INTR_CLEAR0, 0x00 }, ++ { WSA883X_INTR_CLEAR1, 0x00 }, ++ { WSA883X_INTR_LEVEL0, 0x00 }, ++ { WSA883X_INTR_LEVEL1, 0x00 }, ++ { WSA883X_INTR_SET0, 0x00 }, ++ { WSA883X_INTR_SET1, 0x00 }, ++ { WSA883X_INTR_TEST0, 0x00 }, ++ { WSA883X_INTR_TEST1, 0x00 }, ++ { WSA883X_OTP_CTRL0, 0x00 }, ++ { WSA883X_OTP_CTRL1, 0x00 }, ++ { WSA883X_HDRIVE_CTL_GROUP1, 0x00 }, ++ { WSA883X_PIN_CTL, 0x04 }, ++ { WSA883X_PIN_CTL_OE, 0x00 }, ++ { WSA883X_PIN_WDATA_IOPAD, 0x00 }, ++ { WSA883X_PIN_STATUS, 0x00 }, ++ { WSA883X_I2C_SLAVE_CTL, 0x00 }, ++ { WSA883X_PDM_TEST_MODE, 0x00 }, ++ { WSA883X_ATE_TEST_MODE, 0x00 }, ++ { WSA883X_DIG_DEBUG_MODE, 0x00 }, ++ { WSA883X_DIG_DEBUG_SEL, 0x00 }, ++ { WSA883X_DIG_DEBUG_EN, 0x00 }, ++ { WSA883X_SWR_HM_TEST0, 0x08 }, ++ { WSA883X_SWR_HM_TEST1, 0x00 }, ++ { WSA883X_SWR_PAD_CTL, 0x37 }, ++ { WSA883X_TADC_DETECT_DBG_CTL, 0x00 }, ++ { WSA883X_TADC_DEBUG_MSB, 0x00 }, ++ { WSA883X_TADC_DEBUG_LSB, 0x00 }, ++ { WSA883X_SAMPLE_EDGE_SEL, 0x7F }, ++ { WSA883X_SWR_EDGE_SEL, 0x00 }, ++ { WSA883X_TEST_MODE_CTL, 0x04 }, ++ { WSA883X_IOPAD_CTL, 0x00 }, ++ { WSA883X_ANA_CSR_DBG_ADD, 0x00 }, ++ { WSA883X_ANA_CSR_DBG_CTL, 0x12 }, ++ { WSA883X_SPARE_R, 0x00 }, ++ { WSA883X_SPARE_0, 0x00 }, ++ { WSA883X_SPARE_1, 0x00 }, ++ { WSA883X_SPARE_2, 0x00 }, ++ { WSA883X_SCODE, 0x00 }, ++ { WSA883X_OTP_REG_0, 0x05 }, ++ { WSA883X_OTP_REG_1, 0xFF }, ++ { WSA883X_OTP_REG_2, 0xC0 }, ++ { WSA883X_OTP_REG_3, 0xFF }, ++ { WSA883X_OTP_REG_4, 0xC0 }, ++ { WSA883X_OTP_REG_5, 0xFF }, ++ { WSA883X_OTP_REG_6, 0xFF }, ++ { WSA883X_OTP_REG_7, 0xFF }, ++ { WSA883X_OTP_REG_8, 0xFF }, ++ { WSA883X_OTP_REG_9, 0xFF }, ++ { WSA883X_OTP_REG_10, 0xFF }, ++ { WSA883X_OTP_REG_11, 0xFF }, ++ { WSA883X_OTP_REG_12, 0xFF }, ++ { WSA883X_OTP_REG_13, 0xFF }, ++ { WSA883X_OTP_REG_14, 0xFF }, ++ { WSA883X_OTP_REG_15, 0xFF }, ++ { WSA883X_OTP_REG_16, 0xFF }, ++ { WSA883X_OTP_REG_17, 0xFF }, ++ { WSA883X_OTP_REG_18, 0xFF }, ++ { WSA883X_OTP_REG_19, 0xFF }, ++ { WSA883X_OTP_REG_20, 0xFF }, ++ { WSA883X_OTP_REG_21, 0xFF }, ++ { WSA883X_OTP_REG_22, 0xFF }, ++ { WSA883X_OTP_REG_23, 0xFF }, ++ { WSA883X_OTP_REG_24, 0x37 }, ++ { WSA883X_OTP_REG_25, 0x3F }, ++ { WSA883X_OTP_REG_26, 0x03 }, ++ { WSA883X_OTP_REG_27, 0x00 }, ++ { WSA883X_OTP_REG_28, 0x00 }, ++ { WSA883X_OTP_REG_29, 0x00 }, ++ { WSA883X_OTP_REG_30, 0x00 }, ++ { WSA883X_OTP_REG_31, 0x03 }, ++ { WSA883X_OTP_REG_32, 0x00 }, ++ { WSA883X_OTP_REG_33, 0xFF }, ++ { WSA883X_OTP_REG_34, 0x00 }, ++ { WSA883X_OTP_REG_35, 0x00 }, ++ { WSA883X_OTP_REG_63, 0x40 }, ++ { WSA883X_EMEM_0, 0x00 }, ++ { WSA883X_EMEM_1, 0x00 }, ++ { WSA883X_EMEM_2, 0x00 }, ++ { WSA883X_EMEM_3, 0x00 }, ++ { WSA883X_EMEM_4, 0x00 }, ++ { WSA883X_EMEM_5, 0x00 }, ++ { WSA883X_EMEM_6, 0x00 }, ++ { WSA883X_EMEM_7, 0x00 }, ++ { WSA883X_EMEM_8, 0x00 }, ++ { WSA883X_EMEM_9, 0x00 }, ++ { WSA883X_EMEM_10, 0x00 }, ++ { WSA883X_EMEM_11, 0x00 }, ++ { WSA883X_EMEM_12, 0x00 }, ++ { WSA883X_EMEM_13, 0x00 }, ++ { WSA883X_EMEM_14, 0x00 }, ++ { WSA883X_EMEM_15, 0x00 }, ++ { WSA883X_EMEM_16, 0x00 }, ++ { WSA883X_EMEM_17, 0x00 }, ++ { WSA883X_EMEM_18, 0x00 }, ++ { WSA883X_EMEM_19, 0x00 }, ++ { WSA883X_EMEM_20, 0x00 }, ++ { WSA883X_EMEM_21, 0x00 }, ++ { WSA883X_EMEM_22, 0x00 }, ++ { WSA883X_EMEM_23, 0x00 }, ++ { WSA883X_EMEM_24, 0x00 }, ++ { WSA883X_EMEM_25, 0x00 }, ++ { WSA883X_EMEM_26, 0x00 }, ++ { WSA883X_EMEM_27, 0x00 }, ++ { WSA883X_EMEM_28, 0x00 }, ++ { WSA883X_EMEM_29, 0x00 }, ++ { WSA883X_EMEM_30, 0x00 }, ++ { WSA883X_EMEM_31, 0x00 }, ++ { WSA883X_EMEM_32, 0x00 }, ++ { WSA883X_EMEM_33, 0x00 }, ++ { WSA883X_EMEM_34, 0x00 }, ++ { WSA883X_EMEM_35, 0x00 }, ++ { WSA883X_EMEM_36, 0x00 }, ++ { WSA883X_EMEM_37, 0x00 }, ++ { WSA883X_EMEM_38, 0x00 }, ++ { WSA883X_EMEM_39, 0x00 }, ++ { WSA883X_EMEM_40, 0x00 }, ++ { WSA883X_EMEM_41, 0x00 }, ++ { WSA883X_EMEM_42, 0x00 }, ++ { WSA883X_EMEM_43, 0x00 }, ++ { WSA883X_EMEM_44, 0x00 }, ++ { WSA883X_EMEM_45, 0x00 }, ++ { WSA883X_EMEM_46, 0x00 }, ++ { WSA883X_EMEM_47, 0x00 }, ++ { WSA883X_EMEM_48, 0x00 }, ++ { WSA883X_EMEM_49, 0x00 }, ++ { WSA883X_EMEM_50, 0x00 }, ++ { WSA883X_EMEM_51, 0x00 }, ++ { WSA883X_EMEM_52, 0x00 }, ++ { WSA883X_EMEM_53, 0x00 }, ++ { WSA883X_EMEM_54, 0x00 }, ++ { WSA883X_EMEM_55, 0x00 }, ++ { WSA883X_EMEM_56, 0x00 }, ++ { WSA883X_EMEM_57, 0x00 }, ++ { WSA883X_EMEM_58, 0x00 }, ++ { WSA883X_EMEM_59, 0x00 }, ++ { WSA883X_EMEM_60, 0x00 }, ++ { WSA883X_EMEM_61, 0x00 }, ++ { WSA883X_EMEM_62, 0x00 }, ++ { WSA883X_EMEM_63, 0x00 }, ++}; ++ ++static bool wsa883x_readonly_register(struct device *dev, unsigned int reg) ++{ ++ switch (reg) { ++ case WSA883X_DOUT_MSB: ++ case WSA883X_DOUT_LSB: ++ case WSA883X_STATUS: ++ case WSA883X_PA_STATUS0: ++ case WSA883X_PA_STATUS1: ++ case WSA883X_PA_STATUS2: ++ case WSA883X_STATUS_0: ++ case WSA883X_STATUS_1: ++ case WSA883X_CHIP_ID0: ++ case WSA883X_CHIP_ID1: ++ case WSA883X_CHIP_ID2: ++ case WSA883X_CHIP_ID3: ++ case WSA883X_BUS_ID: ++ case WSA883X_PA_FSM_STA: ++ case WSA883X_PA_FSM_ERR_COND: ++ case WSA883X_TEMP_MSB: ++ case WSA883X_TEMP_LSB: ++ case WSA883X_VBAT_DIN_MSB: ++ case WSA883X_VBAT_DIN_LSB: ++ case WSA883X_VBAT_DOUT: ++ case WSA883X_SDM_PDM9_LSB: ++ case WSA883X_SDM_PDM9_MSB: ++ case WSA883X_WAVG_STA: ++ case WSA883X_INTR_STATUS0: ++ case WSA883X_INTR_STATUS1: ++ case WSA883X_OTP_CTRL1: ++ case WSA883X_PIN_STATUS: ++ case WSA883X_ATE_TEST_MODE: ++ case WSA883X_SWR_HM_TEST1: ++ case WSA883X_SPARE_R: ++ case WSA883X_OTP_REG_0: ++ return true; ++ } ++ return false; ++} ++ ++static bool wsa883x_writeable_register(struct device *dev, unsigned int reg) ++{ ++ return !wsa883x_readonly_register(dev, reg); ++} ++ ++static bool wsa883x_volatile_register(struct device *dev, unsigned int reg) ++{ ++ return wsa883x_readonly_register(dev, reg); ++} ++ ++static struct regmap_config wsa883x_regmap_config = { ++ .reg_bits = 32, ++ .val_bits = 8, ++ .cache_type = REGCACHE_RBTREE, ++ .reg_defaults = wsa883x_defaults, ++ .max_register = WSA883X_MAX_REGISTER, ++ .num_reg_defaults = ARRAY_SIZE(wsa883x_defaults), ++ .volatile_reg = wsa883x_volatile_register, ++ .writeable_reg = wsa883x_writeable_register, ++ .reg_format_endian = REGMAP_ENDIAN_NATIVE, ++ .val_format_endian = REGMAP_ENDIAN_NATIVE, ++ .can_multi_write = true, ++ .use_single_read = true, ++}; ++ ++static const struct reg_sequence reg_init[] = { ++ {WSA883X_PA_FSM_BYP, 0x00}, ++ {WSA883X_ADC_6, 0x02}, ++ {WSA883X_CDC_SPK_DSM_A2_0, 0x0A}, ++ {WSA883X_CDC_SPK_DSM_A2_1, 0x08}, ++ {WSA883X_CDC_SPK_DSM_A3_0, 0xF3}, ++ {WSA883X_CDC_SPK_DSM_A3_1, 0x07}, ++ {WSA883X_CDC_SPK_DSM_A4_0, 0x79}, ++ {WSA883X_CDC_SPK_DSM_A4_1, 0x02}, ++ {WSA883X_CDC_SPK_DSM_A5_0, 0x0B}, ++ {WSA883X_CDC_SPK_DSM_A5_1, 0x02}, ++ {WSA883X_CDC_SPK_DSM_A6_0, 0x8A}, ++ {WSA883X_CDC_SPK_DSM_A7_0, 0x9B}, ++ {WSA883X_CDC_SPK_DSM_C_0, 0x68}, ++ {WSA883X_CDC_SPK_DSM_C_1, 0x54}, ++ {WSA883X_CDC_SPK_DSM_C_2, 0xF2}, ++ {WSA883X_CDC_SPK_DSM_C_3, 0x20}, ++ {WSA883X_CDC_SPK_DSM_R1, 0x83}, ++ {WSA883X_CDC_SPK_DSM_R2, 0x7F}, ++ {WSA883X_CDC_SPK_DSM_R3, 0x9D}, ++ {WSA883X_CDC_SPK_DSM_R4, 0x82}, ++ {WSA883X_CDC_SPK_DSM_R5, 0x8B}, ++ {WSA883X_CDC_SPK_DSM_R6, 0x9B}, ++ {WSA883X_CDC_SPK_DSM_R7, 0x3F}, ++ {WSA883X_VBAT_SNS, 0x20}, ++ {WSA883X_DRE_CTL_0, 0x92}, ++ {WSA883X_DRE_IDLE_DET_CTL, 0x0F}, ++ {WSA883X_CURRENT_LIMIT, 0xC4}, ++ {WSA883X_VAGC_TIME, 0x0F}, ++ {WSA883X_VAGC_ATTN_LVL_1_2, 0x00}, ++ {WSA883X_VAGC_ATTN_LVL_3, 0x01}, ++ {WSA883X_VAGC_CTL, 0x01}, ++ {WSA883X_TAGC_CTL, 0x1A}, ++ {WSA883X_TAGC_TIME, 0x2C}, ++ {WSA883X_TEMP_CONFIG0, 0x02}, ++ {WSA883X_TEMP_CONFIG1, 0x02}, ++ {WSA883X_OTP_REG_1, 0x49}, ++ {WSA883X_OTP_REG_2, 0x80}, ++ {WSA883X_OTP_REG_3, 0xC9}, ++ {WSA883X_OTP_REG_4, 0x40}, ++ {WSA883X_TAGC_CTL, 0x1B}, ++ {WSA883X_ADC_2, 0x00}, ++ {WSA883X_ADC_7, 0x85}, ++ {WSA883X_ADC_7, 0x87}, ++ {WSA883X_CKWD_CTL_0, 0x14}, ++ {WSA883X_CKWD_CTL_1, 0x1B}, ++ {WSA883X_GMAMP_SUP1, 0xE2}, ++}; ++ ++static void wsa883x_init(struct wsa883x_priv *wsa883x) ++{ ++ struct regmap *regmap = wsa883x->regmap; ++ int variant, version; ++ ++ regmap_read(regmap, WSA883X_OTP_REG_0, &variant); ++ wsa883x->variant = variant & WSA883X_ID_MASK; ++ ++ regmap_read(regmap, WSA883X_CHIP_ID0, &version); ++ wsa883x->version = version; ++ ++ switch (wsa883x->variant) { ++ case WSA8830: ++ dev_info(wsa883x->dev, "WSA883X Version 1_%d, Variant: WSA8830\n", ++ wsa883x->version); ++ break; ++ case WSA8835: ++ dev_info(wsa883x->dev, "WSA883X Version 1_%d, Variant: WSA8835\n", ++ wsa883x->version); ++ break; ++ case WSA8832: ++ dev_info(wsa883x->dev, "WSA883X Version 1_%d, Variant: WSA8832\n", ++ wsa883x->version); ++ break; ++ case WSA8835_V2: ++ dev_info(wsa883x->dev, "WSA883X Version 1_%d, Variant: WSA8835_V2\n", ++ wsa883x->version); ++ break; ++ default: ++ break; ++ } ++ ++ wsa883x->comp_offset = COMP_OFFSET2; ++ ++ /* Initial settings */ ++ regmap_multi_reg_write(regmap, reg_init, ARRAY_SIZE(reg_init)); ++ ++ if (wsa883x->variant == WSA8830 || wsa883x->variant == WSA8832) { ++ wsa883x->comp_offset = COMP_OFFSET3; ++ regmap_update_bits(regmap, WSA883X_DRE_CTL_0, ++ WSA883X_DRE_OFFSET_MASK, ++ wsa883x->comp_offset); ++ } ++} ++ ++static int wsa883x_update_status(struct sdw_slave *slave, ++ enum sdw_slave_status status) ++{ ++ struct wsa883x_priv *wsa883x = dev_get_drvdata(&slave->dev); ++ ++ if (status == SDW_SLAVE_ATTACHED && slave->dev_num > 0) ++ wsa883x_init(wsa883x); ++ ++ return 0; ++} ++ ++static int wsa883x_port_prep(struct sdw_slave *slave, ++ struct sdw_prepare_ch *prepare_ch, ++ enum sdw_port_prep_ops state) ++{ ++ struct wsa883x_priv *wsa883x = dev_get_drvdata(&slave->dev); ++ ++ if (state == SDW_OPS_PORT_POST_PREP) ++ wsa883x->port_prepared[prepare_ch->num - 1] = true; ++ else ++ wsa883x->port_prepared[prepare_ch->num - 1] = false; ++ ++ return 0; ++} ++ ++static struct sdw_slave_ops wsa883x_slave_ops = { ++ .update_status = wsa883x_update_status, ++ .port_prep = wsa883x_port_prep, ++}; ++ ++static int wsa883x_codec_probe(struct snd_soc_component *comp) ++{ ++ struct wsa883x_priv *wsa883x = snd_soc_component_get_drvdata(comp); ++ ++ snd_soc_component_init_regmap(comp, wsa883x->regmap); ++ ++ return 0; ++} ++ ++static const struct snd_soc_component_driver wsa883x_component_drv = { ++ .name = "WSA883x", ++ .probe = wsa883x_codec_probe, ++}; ++ ++static int wsa883x_hw_params(struct snd_pcm_substream *substream, ++ struct snd_pcm_hw_params *params, ++ struct snd_soc_dai *dai) ++{ ++ struct wsa883x_priv *wsa883x = dev_get_drvdata(dai->dev); ++ int i; ++ ++ wsa883x->active_ports = 0; ++ for (i = 0; i < WSA883X_MAX_SWR_PORTS; i++) { ++ if (!wsa883x->port_enable[i]) ++ continue; ++ ++ wsa883x->port_config[wsa883x->active_ports] = wsa883x_pconfig[i]; ++ wsa883x->active_ports++; ++ } ++ ++ wsa883x->sconfig.frame_rate = params_rate(params); ++ ++ return sdw_stream_add_slave(wsa883x->slave, &wsa883x->sconfig, ++ wsa883x->port_config, wsa883x->active_ports, ++ wsa883x->sruntime); ++} ++ ++static int wsa883x_hw_free(struct snd_pcm_substream *substream, ++ struct snd_soc_dai *dai) ++{ ++ struct wsa883x_priv *wsa883x = dev_get_drvdata(dai->dev); ++ ++ sdw_stream_remove_slave(wsa883x->slave, wsa883x->sruntime); ++ ++ return 0; ++} ++ ++static int wsa883x_set_sdw_stream(struct snd_soc_dai *dai, ++ void *stream, int direction) ++{ ++ struct wsa883x_priv *wsa883x = dev_get_drvdata(dai->dev); ++ ++ wsa883x->sruntime = stream; ++ ++ return 0; ++} ++ ++static int wsa883x_digital_mute(struct snd_soc_dai *dai, int mute, int stream) ++{ ++ struct snd_soc_component *component = dai->component; ++ ++ if (mute) { ++ snd_soc_component_write_field(component, WSA883X_DRE_CTL_1, ++ WSA883X_DRE_GAIN_EN_MASK, 0); ++ snd_soc_component_write_field(component, WSA883X_PA_FSM_CTL, ++ WSA883X_GLOBAL_PA_EN_MASK, 0); ++ ++ } else { ++ snd_soc_component_write_field(component, WSA883X_DRE_CTL_1, ++ WSA883X_DRE_GAIN_EN_MASK, ++ WSA883X_DRE_GAIN_FROM_CSR); ++ snd_soc_component_write_field(component, WSA883X_PA_FSM_CTL, ++ WSA883X_GLOBAL_PA_EN_MASK, 1); ++ ++ } ++ ++ return 0; ++} ++ ++static const struct snd_soc_dai_ops wsa883x_dai_ops = { ++ .hw_params = wsa883x_hw_params, ++ .hw_free = wsa883x_hw_free, ++ .mute_stream = wsa883x_digital_mute, ++ .set_stream = wsa883x_set_sdw_stream, ++}; ++ ++static struct snd_soc_dai_driver wsa883x_dais[] = { ++ { ++ .name = "SPKR", ++ .playback = { ++ .stream_name = "SPKR Playback", ++ .rates = WSA883X_RATES | WSA883X_FRAC_RATES, ++ .formats = WSA883X_FORMATS, ++ .rate_max = 8000, ++ .rate_min = 352800, ++ .channels_min = 1, ++ .channels_max = 1, ++ }, ++ .ops = &wsa883x_dai_ops, ++ }, ++}; ++ ++static int wsa883x_probe(struct sdw_slave *pdev, ++ const struct sdw_device_id *id) ++{ ++ struct wsa883x_priv *wsa883x; ++ struct device *dev = &pdev->dev; ++ int ret; ++ ++ wsa883x = devm_kzalloc(&pdev->dev, sizeof(*wsa883x), GFP_KERNEL); ++ if (!wsa883x) ++ return -ENOMEM; ++ ++ wsa883x->vdd = devm_regulator_get(dev, "vdd"); ++ if (IS_ERR(wsa883x->vdd)) { ++ dev_err(dev, "No vdd regulator found\n"); ++ return PTR_ERR(wsa883x->vdd); ++ } ++ ++ ret = regulator_enable(wsa883x->vdd); ++ if (ret) { ++ dev_err(dev, "Failed to enable vdd regulator (%d)\n", ret); ++ return ret; ++ } ++ ++ wsa883x->sd_n = devm_gpiod_get_optional(&pdev->dev, "powerdown", ++ GPIOD_FLAGS_BIT_NONEXCLUSIVE); ++ if (IS_ERR(wsa883x->sd_n)) { ++ dev_err(&pdev->dev, "Shutdown Control GPIO not found\n"); ++ ret = PTR_ERR(wsa883x->sd_n); ++ goto err; ++ } ++ ++ dev_set_drvdata(&pdev->dev, wsa883x); ++ wsa883x->slave = pdev; ++ wsa883x->dev = &pdev->dev; ++ wsa883x->sconfig.ch_count = 1; ++ wsa883x->sconfig.bps = 1; ++ wsa883x->sconfig.direction = SDW_DATA_DIR_RX; ++ wsa883x->sconfig.type = SDW_STREAM_PDM; ++ ++ pdev->prop.sink_ports = GENMASK(WSA883X_MAX_SWR_PORTS, 0); ++ pdev->prop.sink_dpn_prop = wsa_sink_dpn_prop; ++ pdev->prop.scp_int1_mask = SDW_SCP_INT1_BUS_CLASH | SDW_SCP_INT1_PARITY; ++ gpiod_direction_output(wsa883x->sd_n, 1); ++ ++ wsa883x->regmap = devm_regmap_init_sdw(pdev, &wsa883x_regmap_config); ++ if (IS_ERR(wsa883x->regmap)) { ++ dev_err(&pdev->dev, "regmap_init failed\n"); ++ ret = PTR_ERR(wsa883x->regmap); ++ goto err; ++ } ++ pm_runtime_set_autosuspend_delay(dev, 3000); ++ pm_runtime_use_autosuspend(dev); ++ pm_runtime_mark_last_busy(dev); ++ pm_runtime_set_active(dev); ++ pm_runtime_enable(dev); ++ ++ ret = devm_snd_soc_register_component(&pdev->dev, ++ &wsa883x_component_drv, ++ wsa883x_dais, ++ ARRAY_SIZE(wsa883x_dais)); ++err: ++ if (ret) ++ regulator_disable(wsa883x->vdd); ++ ++ return ret; ++ ++} ++ ++static int __maybe_unused wsa883x_runtime_suspend(struct device *dev) ++{ ++ struct regmap *regmap = dev_get_regmap(dev, NULL); ++ struct wsa883x_priv *wsa883x = dev_get_drvdata(dev); ++ ++ gpiod_direction_output(wsa883x->sd_n, 0); ++ ++ regcache_cache_only(regmap, true); ++ regcache_mark_dirty(regmap); ++ ++ regulator_disable(wsa883x->vdd); ++ return 0; ++} ++ ++static int __maybe_unused wsa883x_runtime_resume(struct device *dev) ++{ ++ struct sdw_slave *slave = dev_to_sdw_dev(dev); ++ struct regmap *regmap = dev_get_regmap(dev, NULL); ++ struct wsa883x_priv *wsa883x = dev_get_drvdata(dev); ++ int ret; ++ ++ ret = regulator_enable(wsa883x->vdd); ++ if (ret) { ++ dev_err(dev, "Failed to enable vdd regulator (%d)\n", ret); ++ return ret; ++ } ++ ++ gpiod_direction_output(wsa883x->sd_n, 1); ++ ++ wait_for_completion_timeout(&slave->initialization_complete, ++ msecs_to_jiffies(WSA883X_PROBE_TIMEOUT)); ++ ++ usleep_range(20000, 20010); ++ regcache_cache_only(regmap, false); ++ regcache_sync(regmap); ++ ++ return 0; ++} ++ ++static const struct dev_pm_ops wsa883x_pm_ops = { ++ SET_RUNTIME_PM_OPS(wsa883x_runtime_suspend, wsa883x_runtime_resume, NULL) ++}; ++ ++static const struct sdw_device_id wsa883x_swr_id[] = { ++ SDW_SLAVE_ENTRY(0x0217, 0x0202, 0), ++ {}, ++}; ++ ++static struct sdw_driver wsa883x_codec_driver = { ++ .driver = { ++ .name = "wsa883x-codec", ++ .pm = &wsa883x_pm_ops, ++ .suppress_bind_attrs = true, ++ }, ++ .probe = wsa883x_probe, ++ .ops = &wsa883x_slave_ops, ++ .id_table = wsa883x_swr_id, ++}; ++ ++module_sdw_driver(wsa883x_codec_driver); ++ ++MODULE_DESCRIPTION("WSA883x codec driver"); ++MODULE_LICENSE("GPL"); +-- +2.42.0 + diff --git a/queue-5.15/asoc-codecs-constify-static-sdw_slave_ops-struct.patch b/queue-5.15/asoc-codecs-constify-static-sdw_slave_ops-struct.patch new file mode 100644 index 00000000000..b2509dad29d --- /dev/null +++ b/queue-5.15/asoc-codecs-constify-static-sdw_slave_ops-struct.patch @@ -0,0 +1,121 @@ +From 22c59dbef68cd57b47ba1970546156babadbdc11 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 24 Jan 2023 17:39:51 +0100 +Subject: ASoC: codecs: constify static sdw_slave_ops struct + +From: Krzysztof Kozlowski + +[ Upstream commit 65b7b869da9bd3bd0b9fa60e6fe557bfbc0a75e8 ] + +The struct sdw_slave_ops is not modified and sdw_driver takes pointer to +const, so make it a const for code safety. + +Signed-off-by: Krzysztof Kozlowski +Link: https://lore.kernel.org/r/20230124163953.345949-1-krzysztof.kozlowski@linaro.org +Signed-off-by: Mark Brown +Stable-dep-of: da29b94ed354 ("ASoC: codecs: wcd938x: fix resource leaks on bind errors") +Signed-off-by: Sasha Levin +--- + sound/soc/codecs/rt1316-sdw.c | 2 +- + sound/soc/codecs/rt1318-sdw.c | 2 +- + sound/soc/codecs/rt711-sdca-sdw.c | 2 +- + sound/soc/codecs/rt715-sdca-sdw.c | 2 +- + sound/soc/codecs/wcd938x-sdw.c | 2 +- + sound/soc/codecs/wsa881x.c | 2 +- + sound/soc/codecs/wsa883x.c | 2 +- + 7 files changed, 7 insertions(+), 7 deletions(-) + +diff --git a/sound/soc/codecs/rt1316-sdw.c b/sound/soc/codecs/rt1316-sdw.c +index 1e04aa8ab1666..41f37ff421430 100644 +--- a/sound/soc/codecs/rt1316-sdw.c ++++ b/sound/soc/codecs/rt1316-sdw.c +@@ -585,7 +585,7 @@ static int rt1316_sdw_pcm_hw_free(struct snd_pcm_substream *substream, + * slave_ops: callbacks for get_clock_stop_mode, clock_stop and + * port_prep are not defined for now + */ +-static struct sdw_slave_ops rt1316_slave_ops = { ++static const struct sdw_slave_ops rt1316_slave_ops = { + .read_prop = rt1316_read_prop, + .update_status = rt1316_update_status, + }; +diff --git a/sound/soc/codecs/rt1318-sdw.c b/sound/soc/codecs/rt1318-sdw.c +index f85f5ab2c6d04..c6ec86e97a6e7 100644 +--- a/sound/soc/codecs/rt1318-sdw.c ++++ b/sound/soc/codecs/rt1318-sdw.c +@@ -697,7 +697,7 @@ static int rt1318_sdw_pcm_hw_free(struct snd_pcm_substream *substream, + * slave_ops: callbacks for get_clock_stop_mode, clock_stop and + * port_prep are not defined for now + */ +-static struct sdw_slave_ops rt1318_slave_ops = { ++static const struct sdw_slave_ops rt1318_slave_ops = { + .read_prop = rt1318_read_prop, + .update_status = rt1318_update_status, + }; +diff --git a/sound/soc/codecs/rt711-sdca-sdw.c b/sound/soc/codecs/rt711-sdca-sdw.c +index 4faf6b8544ddd..48ae52d2e01b9 100644 +--- a/sound/soc/codecs/rt711-sdca-sdw.c ++++ b/sound/soc/codecs/rt711-sdca-sdw.c +@@ -338,7 +338,7 @@ static int rt711_sdca_interrupt_callback(struct sdw_slave *slave, + return ret; + } + +-static struct sdw_slave_ops rt711_sdca_slave_ops = { ++static const struct sdw_slave_ops rt711_sdca_slave_ops = { + .read_prop = rt711_sdca_read_prop, + .interrupt_callback = rt711_sdca_interrupt_callback, + .update_status = rt711_sdca_update_status, +diff --git a/sound/soc/codecs/rt715-sdca-sdw.c b/sound/soc/codecs/rt715-sdca-sdw.c +index 85abf8073c278..2d72a943f982b 100644 +--- a/sound/soc/codecs/rt715-sdca-sdw.c ++++ b/sound/soc/codecs/rt715-sdca-sdw.c +@@ -172,7 +172,7 @@ static int rt715_sdca_read_prop(struct sdw_slave *slave) + return 0; + } + +-static struct sdw_slave_ops rt715_sdca_slave_ops = { ++static const struct sdw_slave_ops rt715_sdca_slave_ops = { + .read_prop = rt715_sdca_read_prop, + .update_status = rt715_sdca_update_status, + }; +diff --git a/sound/soc/codecs/wcd938x-sdw.c b/sound/soc/codecs/wcd938x-sdw.c +index 84a67bd98dc05..f3c9534ae9ef2 100644 +--- a/sound/soc/codecs/wcd938x-sdw.c ++++ b/sound/soc/codecs/wcd938x-sdw.c +@@ -191,7 +191,7 @@ static int wcd9380_interrupt_callback(struct sdw_slave *slave, + return IRQ_HANDLED; + } + +-static struct sdw_slave_ops wcd9380_slave_ops = { ++static const struct sdw_slave_ops wcd9380_slave_ops = { + .update_status = wcd9380_update_status, + .interrupt_callback = wcd9380_interrupt_callback, + .bus_config = wcd9380_bus_config, +diff --git a/sound/soc/codecs/wsa881x.c b/sound/soc/codecs/wsa881x.c +index 8559047694873..67f43b5a34e56 100644 +--- a/sound/soc/codecs/wsa881x.c ++++ b/sound/soc/codecs/wsa881x.c +@@ -1090,7 +1090,7 @@ static int wsa881x_bus_config(struct sdw_slave *slave, + return 0; + } + +-static struct sdw_slave_ops wsa881x_slave_ops = { ++static const struct sdw_slave_ops wsa881x_slave_ops = { + .update_status = wsa881x_update_status, + .bus_config = wsa881x_bus_config, + .port_prep = wsa881x_port_prep, +diff --git a/sound/soc/codecs/wsa883x.c b/sound/soc/codecs/wsa883x.c +index 856709ec017e6..9cc132c7ccf74 100644 +--- a/sound/soc/codecs/wsa883x.c ++++ b/sound/soc/codecs/wsa883x.c +@@ -1061,7 +1061,7 @@ static int wsa883x_port_prep(struct sdw_slave *slave, + return 0; + } + +-static struct sdw_slave_ops wsa883x_slave_ops = { ++static const struct sdw_slave_ops wsa883x_slave_ops = { + .update_status = wsa883x_update_status, + .port_prep = wsa883x_port_prep, + }; +-- +2.42.0 + diff --git a/queue-5.15/asoc-codecs-wcd938x-convert-to-platform-remove-callb.patch b/queue-5.15/asoc-codecs-wcd938x-convert-to-platform-remove-callb.patch new file mode 100644 index 00000000000..64f4677cbbb --- /dev/null +++ b/queue-5.15/asoc-codecs-wcd938x-convert-to-platform-remove-callb.patch @@ -0,0 +1,64 @@ +From 1c3a41eeacbfc67d9be1a73a59cb252c60b1ac64 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 15 Mar 2023 16:05:48 +0100 +Subject: ASoC: codecs: wcd938x: Convert to platform remove callback returning + void +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Uwe Kleine-König + +[ Upstream commit 7cd686a59b36860511965882dad1f76df2c25766 ] + +The .remove() callback for a platform driver returns an int which makes +many driver authors wrongly assume it's possible to do error handling by +returning an error code. However the value returned is (mostly) ignored +and this typically results in resource leaks. To improve here there is a +quest to make the remove callback return void. In the first step of this +quest all drivers are converted to .remove_new() which already returns +void. + +Trivially convert this driver from always returning zero in the remove +callback to the void returning variant. + +Signed-off-by: Uwe Kleine-König +Acked-by: Takashi Iwai +Acked-by: Nicolas Ferre +Link: https://lore.kernel.org/r/20230315150745.67084-57-u.kleine-koenig@pengutronix.de +Signed-off-by: Mark Brown +Stable-dep-of: 69a026a2357e ("ASoC: codecs: wcd938x: fix regulator leaks on probe errors") +Signed-off-by: Sasha Levin +--- + sound/soc/codecs/wcd938x.c | 6 ++---- + 1 file changed, 2 insertions(+), 4 deletions(-) + +diff --git a/sound/soc/codecs/wcd938x.c b/sound/soc/codecs/wcd938x.c +index e68992b704cfa..00538cf86b87f 100644 +--- a/sound/soc/codecs/wcd938x.c ++++ b/sound/soc/codecs/wcd938x.c +@@ -3601,11 +3601,9 @@ static int wcd938x_probe(struct platform_device *pdev) + return 0; + } + +-static int wcd938x_remove(struct platform_device *pdev) ++static void wcd938x_remove(struct platform_device *pdev) + { + component_master_del(&pdev->dev, &wcd938x_comp_ops); +- +- return 0; + } + + #if defined(CONFIG_OF) +@@ -3619,7 +3617,7 @@ MODULE_DEVICE_TABLE(of, wcd938x_dt_match); + + static struct platform_driver wcd938x_codec_driver = { + .probe = wcd938x_probe, +- .remove = wcd938x_remove, ++ .remove_new = wcd938x_remove, + .driver = { + .name = "wcd938x_codec", + .of_match_table = of_match_ptr(wcd938x_dt_match), +-- +2.42.0 + diff --git a/queue-5.15/asoc-codecs-wcd938x-fix-accessing-regmap-on-unattach.patch b/queue-5.15/asoc-codecs-wcd938x-fix-accessing-regmap-on-unattach.patch new file mode 100644 index 00000000000..246e50ed9da --- /dev/null +++ b/queue-5.15/asoc-codecs-wcd938x-fix-accessing-regmap-on-unattach.patch @@ -0,0 +1,2169 @@ +From 48b1f249eb428f77e6cc22daa0c9b10cfc7e4da8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 3 May 2023 16:41:02 +0200 +Subject: ASoC: codecs: wcd938x: fix accessing regmap on unattached devices + +From: Krzysztof Kozlowski + +[ Upstream commit 84822215acd15bd86a7759a835271e63bba83a7b ] + +The WCD938x comes with three devices on two Linux drivers: +1. RX Soundwire device (wcd938x-sdw.c driver), +2. TX Soundwire device, which is used to access devices via regmap (also + wcd938x-sdw.c driver), +3. platform device (wcd938x.c driver) - glue and component master, + actually having most of the code using TX Soundwire device regmap. + +When RX and TX Soundwire devices probe, the component master (platform +device) bind tries to write micbias configuration via TX Soundwire +regmap. This might happen before TX Soundwire enumerates, so the regmap +access fails. On Qualcomm SM8550 board with WCD9385: + + qcom-soundwire 6d30000.soundwire-controller: Qualcomm Soundwire controller v2.0.0 Registered + wcd938x_codec audio-codec: bound sdw:0:0217:010d:00:4 (ops wcd938x_sdw_component_ops) + wcd938x_codec audio-codec: bound sdw:0:0217:010d:00:3 (ops wcd938x_sdw_component_ops) + qcom-soundwire 6ad0000.soundwire-controller: swrm_wait_for_wr_fifo_avail err write overflow + +Fix the issue by: +1. Moving the regmap creation from platform device to TX Soundwire + device. The regmap settings are moved as-is with one difference: + making the wcd938x_regmap_config const. +2. Using regmap in cache only mode till the actual TX Soundwire device + enumerates and then sync the regmap cache. + +Cc: # v3.14+ +Signed-off-by: Krzysztof Kozlowski +Reviewed-by: Pierre-Louis Bossart +Message-Id: <20230503144102.242240-1-krzysztof.kozlowski@linaro.org> +Signed-off-by: Mark Brown +Stable-dep-of: da29b94ed354 ("ASoC: codecs: wcd938x: fix resource leaks on bind errors") +Signed-off-by: Sasha Levin +--- + sound/soc/codecs/wcd938x-sdw.c | 1037 +++++++++++++++++++++++++++++++- + sound/soc/codecs/wcd938x.c | 1003 +----------------------------- + sound/soc/codecs/wcd938x.h | 1 + + 3 files changed, 1030 insertions(+), 1011 deletions(-) + +diff --git a/sound/soc/codecs/wcd938x-sdw.c b/sound/soc/codecs/wcd938x-sdw.c +index f3c9534ae9ef2..f233d9d4a7717 100644 +--- a/sound/soc/codecs/wcd938x-sdw.c ++++ b/sound/soc/codecs/wcd938x-sdw.c +@@ -161,6 +161,14 @@ EXPORT_SYMBOL_GPL(wcd938x_sdw_set_sdw_stream); + static int wcd9380_update_status(struct sdw_slave *slave, + enum sdw_slave_status status) + { ++ struct wcd938x_sdw_priv *wcd = dev_get_drvdata(&slave->dev); ++ ++ if (wcd->regmap && (status == SDW_SLAVE_ATTACHED)) { ++ /* Write out any cached changes that happened between probe and attach */ ++ regcache_cache_only(wcd->regmap, false); ++ return regcache_sync(wcd->regmap); ++ } ++ + return 0; + } + +@@ -177,20 +185,1014 @@ static int wcd9380_interrupt_callback(struct sdw_slave *slave, + { + struct wcd938x_sdw_priv *wcd = dev_get_drvdata(&slave->dev); + struct irq_domain *slave_irq = wcd->slave_irq; +- struct regmap *regmap = dev_get_regmap(&slave->dev, NULL); + u32 sts1, sts2, sts3; + + do { + handle_nested_irq(irq_find_mapping(slave_irq, 0)); +- regmap_read(regmap, WCD938X_DIGITAL_INTR_STATUS_0, &sts1); +- regmap_read(regmap, WCD938X_DIGITAL_INTR_STATUS_1, &sts2); +- regmap_read(regmap, WCD938X_DIGITAL_INTR_STATUS_2, &sts3); ++ regmap_read(wcd->regmap, WCD938X_DIGITAL_INTR_STATUS_0, &sts1); ++ regmap_read(wcd->regmap, WCD938X_DIGITAL_INTR_STATUS_1, &sts2); ++ regmap_read(wcd->regmap, WCD938X_DIGITAL_INTR_STATUS_2, &sts3); + + } while (sts1 || sts2 || sts3); + + return IRQ_HANDLED; + } + ++static const struct reg_default wcd938x_defaults[] = { ++ {WCD938X_ANA_PAGE_REGISTER, 0x00}, ++ {WCD938X_ANA_BIAS, 0x00}, ++ {WCD938X_ANA_RX_SUPPLIES, 0x00}, ++ {WCD938X_ANA_HPH, 0x0C}, ++ {WCD938X_ANA_EAR, 0x00}, ++ {WCD938X_ANA_EAR_COMPANDER_CTL, 0x02}, ++ {WCD938X_ANA_TX_CH1, 0x20}, ++ {WCD938X_ANA_TX_CH2, 0x00}, ++ {WCD938X_ANA_TX_CH3, 0x20}, ++ {WCD938X_ANA_TX_CH4, 0x00}, ++ {WCD938X_ANA_MICB1_MICB2_DSP_EN_LOGIC, 0x00}, ++ {WCD938X_ANA_MICB3_DSP_EN_LOGIC, 0x00}, ++ {WCD938X_ANA_MBHC_MECH, 0x39}, ++ {WCD938X_ANA_MBHC_ELECT, 0x08}, ++ {WCD938X_ANA_MBHC_ZDET, 0x00}, ++ {WCD938X_ANA_MBHC_RESULT_1, 0x00}, ++ {WCD938X_ANA_MBHC_RESULT_2, 0x00}, ++ {WCD938X_ANA_MBHC_RESULT_3, 0x00}, ++ {WCD938X_ANA_MBHC_BTN0, 0x00}, ++ {WCD938X_ANA_MBHC_BTN1, 0x10}, ++ {WCD938X_ANA_MBHC_BTN2, 0x20}, ++ {WCD938X_ANA_MBHC_BTN3, 0x30}, ++ {WCD938X_ANA_MBHC_BTN4, 0x40}, ++ {WCD938X_ANA_MBHC_BTN5, 0x50}, ++ {WCD938X_ANA_MBHC_BTN6, 0x60}, ++ {WCD938X_ANA_MBHC_BTN7, 0x70}, ++ {WCD938X_ANA_MICB1, 0x10}, ++ {WCD938X_ANA_MICB2, 0x10}, ++ {WCD938X_ANA_MICB2_RAMP, 0x00}, ++ {WCD938X_ANA_MICB3, 0x10}, ++ {WCD938X_ANA_MICB4, 0x10}, ++ {WCD938X_BIAS_CTL, 0x2A}, ++ {WCD938X_BIAS_VBG_FINE_ADJ, 0x55}, ++ {WCD938X_LDOL_VDDCX_ADJUST, 0x01}, ++ {WCD938X_LDOL_DISABLE_LDOL, 0x00}, ++ {WCD938X_MBHC_CTL_CLK, 0x00}, ++ {WCD938X_MBHC_CTL_ANA, 0x00}, ++ {WCD938X_MBHC_CTL_SPARE_1, 0x00}, ++ {WCD938X_MBHC_CTL_SPARE_2, 0x00}, ++ {WCD938X_MBHC_CTL_BCS, 0x00}, ++ {WCD938X_MBHC_MOISTURE_DET_FSM_STATUS, 0x00}, ++ {WCD938X_MBHC_TEST_CTL, 0x00}, ++ {WCD938X_LDOH_MODE, 0x2B}, ++ {WCD938X_LDOH_BIAS, 0x68}, ++ {WCD938X_LDOH_STB_LOADS, 0x00}, ++ {WCD938X_LDOH_SLOWRAMP, 0x50}, ++ {WCD938X_MICB1_TEST_CTL_1, 0x1A}, ++ {WCD938X_MICB1_TEST_CTL_2, 0x00}, ++ {WCD938X_MICB1_TEST_CTL_3, 0xA4}, ++ {WCD938X_MICB2_TEST_CTL_1, 0x1A}, ++ {WCD938X_MICB2_TEST_CTL_2, 0x00}, ++ {WCD938X_MICB2_TEST_CTL_3, 0x24}, ++ {WCD938X_MICB3_TEST_CTL_1, 0x1A}, ++ {WCD938X_MICB3_TEST_CTL_2, 0x00}, ++ {WCD938X_MICB3_TEST_CTL_3, 0xA4}, ++ {WCD938X_MICB4_TEST_CTL_1, 0x1A}, ++ {WCD938X_MICB4_TEST_CTL_2, 0x00}, ++ {WCD938X_MICB4_TEST_CTL_3, 0xA4}, ++ {WCD938X_TX_COM_ADC_VCM, 0x39}, ++ {WCD938X_TX_COM_BIAS_ATEST, 0xE0}, ++ {WCD938X_TX_COM_SPARE1, 0x00}, ++ {WCD938X_TX_COM_SPARE2, 0x00}, ++ {WCD938X_TX_COM_TXFE_DIV_CTL, 0x22}, ++ {WCD938X_TX_COM_TXFE_DIV_START, 0x00}, ++ {WCD938X_TX_COM_SPARE3, 0x00}, ++ {WCD938X_TX_COM_SPARE4, 0x00}, ++ {WCD938X_TX_1_2_TEST_EN, 0xCC}, ++ {WCD938X_TX_1_2_ADC_IB, 0xE9}, ++ {WCD938X_TX_1_2_ATEST_REFCTL, 0x0A}, ++ {WCD938X_TX_1_2_TEST_CTL, 0x38}, ++ {WCD938X_TX_1_2_TEST_BLK_EN1, 0xFF}, ++ {WCD938X_TX_1_2_TXFE1_CLKDIV, 0x00}, ++ {WCD938X_TX_1_2_SAR2_ERR, 0x00}, ++ {WCD938X_TX_1_2_SAR1_ERR, 0x00}, ++ {WCD938X_TX_3_4_TEST_EN, 0xCC}, ++ {WCD938X_TX_3_4_ADC_IB, 0xE9}, ++ {WCD938X_TX_3_4_ATEST_REFCTL, 0x0A}, ++ {WCD938X_TX_3_4_TEST_CTL, 0x38}, ++ {WCD938X_TX_3_4_TEST_BLK_EN3, 0xFF}, ++ {WCD938X_TX_3_4_TXFE3_CLKDIV, 0x00}, ++ {WCD938X_TX_3_4_SAR4_ERR, 0x00}, ++ {WCD938X_TX_3_4_SAR3_ERR, 0x00}, ++ {WCD938X_TX_3_4_TEST_BLK_EN2, 0xFB}, ++ {WCD938X_TX_3_4_TXFE2_CLKDIV, 0x00}, ++ {WCD938X_TX_3_4_SPARE1, 0x00}, ++ {WCD938X_TX_3_4_TEST_BLK_EN4, 0xFB}, ++ {WCD938X_TX_3_4_TXFE4_CLKDIV, 0x00}, ++ {WCD938X_TX_3_4_SPARE2, 0x00}, ++ {WCD938X_CLASSH_MODE_1, 0x40}, ++ {WCD938X_CLASSH_MODE_2, 0x3A}, ++ {WCD938X_CLASSH_MODE_3, 0x00}, ++ {WCD938X_CLASSH_CTRL_VCL_1, 0x70}, ++ {WCD938X_CLASSH_CTRL_VCL_2, 0x82}, ++ {WCD938X_CLASSH_CTRL_CCL_1, 0x31}, ++ {WCD938X_CLASSH_CTRL_CCL_2, 0x80}, ++ {WCD938X_CLASSH_CTRL_CCL_3, 0x80}, ++ {WCD938X_CLASSH_CTRL_CCL_4, 0x51}, ++ {WCD938X_CLASSH_CTRL_CCL_5, 0x00}, ++ {WCD938X_CLASSH_BUCK_TMUX_A_D, 0x00}, ++ {WCD938X_CLASSH_BUCK_SW_DRV_CNTL, 0x77}, ++ {WCD938X_CLASSH_SPARE, 0x00}, ++ {WCD938X_FLYBACK_EN, 0x4E}, ++ {WCD938X_FLYBACK_VNEG_CTRL_1, 0x0B}, ++ {WCD938X_FLYBACK_VNEG_CTRL_2, 0x45}, ++ {WCD938X_FLYBACK_VNEG_CTRL_3, 0x74}, ++ {WCD938X_FLYBACK_VNEG_CTRL_4, 0x7F}, ++ {WCD938X_FLYBACK_VNEG_CTRL_5, 0x83}, ++ {WCD938X_FLYBACK_VNEG_CTRL_6, 0x98}, ++ {WCD938X_FLYBACK_VNEG_CTRL_7, 0xA9}, ++ {WCD938X_FLYBACK_VNEG_CTRL_8, 0x68}, ++ {WCD938X_FLYBACK_VNEG_CTRL_9, 0x64}, ++ {WCD938X_FLYBACK_VNEGDAC_CTRL_1, 0xED}, ++ {WCD938X_FLYBACK_VNEGDAC_CTRL_2, 0xF0}, ++ {WCD938X_FLYBACK_VNEGDAC_CTRL_3, 0xA6}, ++ {WCD938X_FLYBACK_CTRL_1, 0x65}, ++ {WCD938X_FLYBACK_TEST_CTL, 0x00}, ++ {WCD938X_RX_AUX_SW_CTL, 0x00}, ++ {WCD938X_RX_PA_AUX_IN_CONN, 0x01}, ++ {WCD938X_RX_TIMER_DIV, 0x32}, ++ {WCD938X_RX_OCP_CTL, 0x1F}, ++ {WCD938X_RX_OCP_COUNT, 0x77}, ++ {WCD938X_RX_BIAS_EAR_DAC, 0xA0}, ++ {WCD938X_RX_BIAS_EAR_AMP, 0xAA}, ++ {WCD938X_RX_BIAS_HPH_LDO, 0xA9}, ++ {WCD938X_RX_BIAS_HPH_PA, 0xAA}, ++ {WCD938X_RX_BIAS_HPH_RDACBUFF_CNP2, 0x8A}, ++ {WCD938X_RX_BIAS_HPH_RDAC_LDO, 0x88}, ++ {WCD938X_RX_BIAS_HPH_CNP1, 0x82}, ++ {WCD938X_RX_BIAS_HPH_LOWPOWER, 0x82}, ++ {WCD938X_RX_BIAS_AUX_DAC, 0xA0}, ++ {WCD938X_RX_BIAS_AUX_AMP, 0xAA}, ++ {WCD938X_RX_BIAS_VNEGDAC_BLEEDER, 0x50}, ++ {WCD938X_RX_BIAS_MISC, 0x00}, ++ {WCD938X_RX_BIAS_BUCK_RST, 0x08}, ++ {WCD938X_RX_BIAS_BUCK_VREF_ERRAMP, 0x44}, ++ {WCD938X_RX_BIAS_FLYB_ERRAMP, 0x40}, ++ {WCD938X_RX_BIAS_FLYB_BUFF, 0xAA}, ++ {WCD938X_RX_BIAS_FLYB_MID_RST, 0x14}, ++ {WCD938X_HPH_L_STATUS, 0x04}, ++ {WCD938X_HPH_R_STATUS, 0x04}, ++ {WCD938X_HPH_CNP_EN, 0x80}, ++ {WCD938X_HPH_CNP_WG_CTL, 0x9A}, ++ {WCD938X_HPH_CNP_WG_TIME, 0x14}, ++ {WCD938X_HPH_OCP_CTL, 0x28}, ++ {WCD938X_HPH_AUTO_CHOP, 0x16}, ++ {WCD938X_HPH_CHOP_CTL, 0x83}, ++ {WCD938X_HPH_PA_CTL1, 0x46}, ++ {WCD938X_HPH_PA_CTL2, 0x50}, ++ {WCD938X_HPH_L_EN, 0x80}, ++ {WCD938X_HPH_L_TEST, 0xE0}, ++ {WCD938X_HPH_L_ATEST, 0x50}, ++ {WCD938X_HPH_R_EN, 0x80}, ++ {WCD938X_HPH_R_TEST, 0xE0}, ++ {WCD938X_HPH_R_ATEST, 0x54}, ++ {WCD938X_HPH_RDAC_CLK_CTL1, 0x99}, ++ {WCD938X_HPH_RDAC_CLK_CTL2, 0x9B}, ++ {WCD938X_HPH_RDAC_LDO_CTL, 0x33}, ++ {WCD938X_HPH_RDAC_CHOP_CLK_LP_CTL, 0x00}, ++ {WCD938X_HPH_REFBUFF_UHQA_CTL, 0x68}, ++ {WCD938X_HPH_REFBUFF_LP_CTL, 0x0E}, ++ {WCD938X_HPH_L_DAC_CTL, 0x20}, ++ {WCD938X_HPH_R_DAC_CTL, 0x20}, ++ {WCD938X_HPH_SURGE_HPHLR_SURGE_COMP_SEL, 0x55}, ++ {WCD938X_HPH_SURGE_HPHLR_SURGE_EN, 0x19}, ++ {WCD938X_HPH_SURGE_HPHLR_SURGE_MISC1, 0xA0}, ++ {WCD938X_HPH_SURGE_HPHLR_SURGE_STATUS, 0x00}, ++ {WCD938X_EAR_EAR_EN_REG, 0x22}, ++ {WCD938X_EAR_EAR_PA_CON, 0x44}, ++ {WCD938X_EAR_EAR_SP_CON, 0xDB}, ++ {WCD938X_EAR_EAR_DAC_CON, 0x80}, ++ {WCD938X_EAR_EAR_CNP_FSM_CON, 0xB2}, ++ {WCD938X_EAR_TEST_CTL, 0x00}, ++ {WCD938X_EAR_STATUS_REG_1, 0x00}, ++ {WCD938X_EAR_STATUS_REG_2, 0x08}, ++ {WCD938X_ANA_NEW_PAGE_REGISTER, 0x00}, ++ {WCD938X_HPH_NEW_ANA_HPH2, 0x00}, ++ {WCD938X_HPH_NEW_ANA_HPH3, 0x00}, ++ {WCD938X_SLEEP_CTL, 0x16}, ++ {WCD938X_SLEEP_WATCHDOG_CTL, 0x00}, ++ {WCD938X_MBHC_NEW_ELECT_REM_CLAMP_CTL, 0x00}, ++ {WCD938X_MBHC_NEW_CTL_1, 0x02}, ++ {WCD938X_MBHC_NEW_CTL_2, 0x05}, ++ {WCD938X_MBHC_NEW_PLUG_DETECT_CTL, 0xE9}, ++ {WCD938X_MBHC_NEW_ZDET_ANA_CTL, 0x0F}, ++ {WCD938X_MBHC_NEW_ZDET_RAMP_CTL, 0x00}, ++ {WCD938X_MBHC_NEW_FSM_STATUS, 0x00}, ++ {WCD938X_MBHC_NEW_ADC_RESULT, 0x00}, ++ {WCD938X_TX_NEW_AMIC_MUX_CFG, 0x00}, ++ {WCD938X_AUX_AUXPA, 0x00}, ++ {WCD938X_LDORXTX_MODE, 0x0C}, ++ {WCD938X_LDORXTX_CONFIG, 0x10}, ++ {WCD938X_DIE_CRACK_DIE_CRK_DET_EN, 0x00}, ++ {WCD938X_DIE_CRACK_DIE_CRK_DET_OUT, 0x00}, ++ {WCD938X_HPH_NEW_INT_RDAC_GAIN_CTL, 0x40}, ++ {WCD938X_HPH_NEW_INT_RDAC_HD2_CTL_L, 0x81}, ++ {WCD938X_HPH_NEW_INT_RDAC_VREF_CTL, 0x10}, ++ {WCD938X_HPH_NEW_INT_RDAC_OVERRIDE_CTL, 0x00}, ++ {WCD938X_HPH_NEW_INT_RDAC_HD2_CTL_R, 0x81}, ++ {WCD938X_HPH_NEW_INT_PA_MISC1, 0x22}, ++ {WCD938X_HPH_NEW_INT_PA_MISC2, 0x00}, ++ {WCD938X_HPH_NEW_INT_PA_RDAC_MISC, 0x00}, ++ {WCD938X_HPH_NEW_INT_HPH_TIMER1, 0xFE}, ++ {WCD938X_HPH_NEW_INT_HPH_TIMER2, 0x02}, ++ {WCD938X_HPH_NEW_INT_HPH_TIMER3, 0x4E}, ++ {WCD938X_HPH_NEW_INT_HPH_TIMER4, 0x54}, ++ {WCD938X_HPH_NEW_INT_PA_RDAC_MISC2, 0x00}, ++ {WCD938X_HPH_NEW_INT_PA_RDAC_MISC3, 0x00}, ++ {WCD938X_HPH_NEW_INT_RDAC_HD2_CTL_L_NEW, 0x90}, ++ {WCD938X_HPH_NEW_INT_RDAC_HD2_CTL_R_NEW, 0x90}, ++ {WCD938X_RX_NEW_INT_HPH_RDAC_BIAS_LOHIFI, 0x62}, ++ {WCD938X_RX_NEW_INT_HPH_RDAC_BIAS_ULP, 0x01}, ++ {WCD938X_RX_NEW_INT_HPH_RDAC_LDO_LP, 0x11}, ++ {WCD938X_MBHC_NEW_INT_MOISTURE_DET_DC_CTRL, 0x57}, ++ {WCD938X_MBHC_NEW_INT_MOISTURE_DET_POLLING_CTRL, 0x01}, ++ {WCD938X_MBHC_NEW_INT_MECH_DET_CURRENT, 0x00}, ++ {WCD938X_MBHC_NEW_INT_SPARE_2, 0x00}, ++ {WCD938X_EAR_INT_NEW_EAR_CHOPPER_CON, 0xA8}, ++ {WCD938X_EAR_INT_NEW_CNP_VCM_CON1, 0x42}, ++ {WCD938X_EAR_INT_NEW_CNP_VCM_CON2, 0x22}, ++ {WCD938X_EAR_INT_NEW_EAR_DYNAMIC_BIAS, 0x00}, ++ {WCD938X_AUX_INT_EN_REG, 0x00}, ++ {WCD938X_AUX_INT_PA_CTRL, 0x06}, ++ {WCD938X_AUX_INT_SP_CTRL, 0xD2}, ++ {WCD938X_AUX_INT_DAC_CTRL, 0x80}, ++ {WCD938X_AUX_INT_CLK_CTRL, 0x50}, ++ {WCD938X_AUX_INT_TEST_CTRL, 0x00}, ++ {WCD938X_AUX_INT_STATUS_REG, 0x00}, ++ {WCD938X_AUX_INT_MISC, 0x00}, ++ {WCD938X_LDORXTX_INT_BIAS, 0x6E}, ++ {WCD938X_LDORXTX_INT_STB_LOADS_DTEST, 0x50}, ++ {WCD938X_LDORXTX_INT_TEST0, 0x1C}, ++ {WCD938X_LDORXTX_INT_STARTUP_TIMER, 0xFF}, ++ {WCD938X_LDORXTX_INT_TEST1, 0x1F}, ++ {WCD938X_LDORXTX_INT_STATUS, 0x00}, ++ {WCD938X_SLEEP_INT_WATCHDOG_CTL_1, 0x0A}, ++ {WCD938X_SLEEP_INT_WATCHDOG_CTL_2, 0x0A}, ++ {WCD938X_DIE_CRACK_INT_DIE_CRK_DET_INT1, 0x02}, ++ {WCD938X_DIE_CRACK_INT_DIE_CRK_DET_INT2, 0x60}, ++ {WCD938X_TX_COM_NEW_INT_TXFE_DIVSTOP_L2, 0xFF}, ++ {WCD938X_TX_COM_NEW_INT_TXFE_DIVSTOP_L1, 0x7F}, ++ {WCD938X_TX_COM_NEW_INT_TXFE_DIVSTOP_L0, 0x3F}, ++ {WCD938X_TX_COM_NEW_INT_TXFE_DIVSTOP_ULP1P2M, 0x1F}, ++ {WCD938X_TX_COM_NEW_INT_TXFE_DIVSTOP_ULP0P6M, 0x0F}, ++ {WCD938X_TX_COM_NEW_INT_TXFE_ICTRL_STG1_L2L1, 0xD7}, ++ {WCD938X_TX_COM_NEW_INT_TXFE_ICTRL_STG1_L0, 0xC8}, ++ {WCD938X_TX_COM_NEW_INT_TXFE_ICTRL_STG1_ULP, 0xC6}, ++ {WCD938X_TX_COM_NEW_INT_TXFE_ICTRL_STG2MAIN_L2L1, 0xD5}, ++ {WCD938X_TX_COM_NEW_INT_TXFE_ICTRL_STG2MAIN_L0, 0xCA}, ++ {WCD938X_TX_COM_NEW_INT_TXFE_ICTRL_STG2MAIN_ULP, 0x05}, ++ {WCD938X_TX_COM_NEW_INT_TXFE_ICTRL_STG2CASC_L2L1L0, 0xA5}, ++ {WCD938X_TX_COM_NEW_INT_TXFE_ICTRL_STG2CASC_ULP, 0x13}, ++ {WCD938X_TX_COM_NEW_INT_TXADC_SCBIAS_L2L1, 0x88}, ++ {WCD938X_TX_COM_NEW_INT_TXADC_SCBIAS_L0ULP, 0x42}, ++ {WCD938X_TX_COM_NEW_INT_TXADC_INT_L2, 0xFF}, ++ {WCD938X_TX_COM_NEW_INT_TXADC_INT_L1, 0x64}, ++ {WCD938X_TX_COM_NEW_INT_TXADC_INT_L0, 0x64}, ++ {WCD938X_TX_COM_NEW_INT_TXADC_INT_ULP, 0x77}, ++ {WCD938X_DIGITAL_PAGE_REGISTER, 0x00}, ++ {WCD938X_DIGITAL_CHIP_ID0, 0x00}, ++ {WCD938X_DIGITAL_CHIP_ID1, 0x00}, ++ {WCD938X_DIGITAL_CHIP_ID2, 0x0D}, ++ {WCD938X_DIGITAL_CHIP_ID3, 0x01}, ++ {WCD938X_DIGITAL_SWR_TX_CLK_RATE, 0x00}, ++ {WCD938X_DIGITAL_CDC_RST_CTL, 0x03}, ++ {WCD938X_DIGITAL_TOP_CLK_CFG, 0x00}, ++ {WCD938X_DIGITAL_CDC_ANA_CLK_CTL, 0x00}, ++ {WCD938X_DIGITAL_CDC_DIG_CLK_CTL, 0xF0}, ++ {WCD938X_DIGITAL_SWR_RST_EN, 0x00}, ++ {WCD938X_DIGITAL_CDC_PATH_MODE, 0x55}, ++ {WCD938X_DIGITAL_CDC_RX_RST, 0x00}, ++ {WCD938X_DIGITAL_CDC_RX0_CTL, 0xFC}, ++ {WCD938X_DIGITAL_CDC_RX1_CTL, 0xFC}, ++ {WCD938X_DIGITAL_CDC_RX2_CTL, 0xFC}, ++ {WCD938X_DIGITAL_CDC_TX_ANA_MODE_0_1, 0x00}, ++ {WCD938X_DIGITAL_CDC_TX_ANA_MODE_2_3, 0x00}, ++ {WCD938X_DIGITAL_CDC_COMP_CTL_0, 0x00}, ++ {WCD938X_DIGITAL_CDC_ANA_TX_CLK_CTL, 0x1E}, ++ {WCD938X_DIGITAL_CDC_HPH_DSM_A1_0, 0x00}, ++ {WCD938X_DIGITAL_CDC_HPH_DSM_A1_1, 0x01}, ++ {WCD938X_DIGITAL_CDC_HPH_DSM_A2_0, 0x63}, ++ {WCD938X_DIGITAL_CDC_HPH_DSM_A2_1, 0x04}, ++ {WCD938X_DIGITAL_CDC_HPH_DSM_A3_0, 0xAC}, ++ {WCD938X_DIGITAL_CDC_HPH_DSM_A3_1, 0x04}, ++ {WCD938X_DIGITAL_CDC_HPH_DSM_A4_0, 0x1A}, ++ {WCD938X_DIGITAL_CDC_HPH_DSM_A4_1, 0x03}, ++ {WCD938X_DIGITAL_CDC_HPH_DSM_A5_0, 0xBC}, ++ {WCD938X_DIGITAL_CDC_HPH_DSM_A5_1, 0x02}, ++ {WCD938X_DIGITAL_CDC_HPH_DSM_A6_0, 0xC7}, ++ {WCD938X_DIGITAL_CDC_HPH_DSM_A7_0, 0xF8}, ++ {WCD938X_DIGITAL_CDC_HPH_DSM_C_0, 0x47}, ++ {WCD938X_DIGITAL_CDC_HPH_DSM_C_1, 0x43}, ++ {WCD938X_DIGITAL_CDC_HPH_DSM_C_2, 0xB1}, ++ {WCD938X_DIGITAL_CDC_HPH_DSM_C_3, 0x17}, ++ {WCD938X_DIGITAL_CDC_HPH_DSM_R1, 0x4D}, ++ {WCD938X_DIGITAL_CDC_HPH_DSM_R2, 0x29}, ++ {WCD938X_DIGITAL_CDC_HPH_DSM_R3, 0x34}, ++ {WCD938X_DIGITAL_CDC_HPH_DSM_R4, 0x59}, ++ {WCD938X_DIGITAL_CDC_HPH_DSM_R5, 0x66}, ++ {WCD938X_DIGITAL_CDC_HPH_DSM_R6, 0x87}, ++ {WCD938X_DIGITAL_CDC_HPH_DSM_R7, 0x64}, ++ {WCD938X_DIGITAL_CDC_AUX_DSM_A1_0, 0x00}, ++ {WCD938X_DIGITAL_CDC_AUX_DSM_A1_1, 0x01}, ++ {WCD938X_DIGITAL_CDC_AUX_DSM_A2_0, 0x96}, ++ {WCD938X_DIGITAL_CDC_AUX_DSM_A2_1, 0x09}, ++ {WCD938X_DIGITAL_CDC_AUX_DSM_A3_0, 0xAB}, ++ {WCD938X_DIGITAL_CDC_AUX_DSM_A3_1, 0x05}, ++ {WCD938X_DIGITAL_CDC_AUX_DSM_A4_0, 0x1C}, ++ {WCD938X_DIGITAL_CDC_AUX_DSM_A4_1, 0x02}, ++ {WCD938X_DIGITAL_CDC_AUX_DSM_A5_0, 0x17}, ++ {WCD938X_DIGITAL_CDC_AUX_DSM_A5_1, 0x02}, ++ {WCD938X_DIGITAL_CDC_AUX_DSM_A6_0, 0xAA}, ++ {WCD938X_DIGITAL_CDC_AUX_DSM_A7_0, 0xE3}, ++ {WCD938X_DIGITAL_CDC_AUX_DSM_C_0, 0x69}, ++ {WCD938X_DIGITAL_CDC_AUX_DSM_C_1, 0x54}, ++ {WCD938X_DIGITAL_CDC_AUX_DSM_C_2, 0x02}, ++ {WCD938X_DIGITAL_CDC_AUX_DSM_C_3, 0x15}, ++ {WCD938X_DIGITAL_CDC_AUX_DSM_R1, 0xA4}, ++ {WCD938X_DIGITAL_CDC_AUX_DSM_R2, 0xB5}, ++ {WCD938X_DIGITAL_CDC_AUX_DSM_R3, 0x86}, ++ {WCD938X_DIGITAL_CDC_AUX_DSM_R4, 0x85}, ++ {WCD938X_DIGITAL_CDC_AUX_DSM_R5, 0xAA}, ++ {WCD938X_DIGITAL_CDC_AUX_DSM_R6, 0xE2}, ++ {WCD938X_DIGITAL_CDC_AUX_DSM_R7, 0x62}, ++ {WCD938X_DIGITAL_CDC_HPH_GAIN_RX_0, 0x55}, ++ {WCD938X_DIGITAL_CDC_HPH_GAIN_RX_1, 0xA9}, ++ {WCD938X_DIGITAL_CDC_HPH_GAIN_DSD_0, 0x3D}, ++ {WCD938X_DIGITAL_CDC_HPH_GAIN_DSD_1, 0x2E}, ++ {WCD938X_DIGITAL_CDC_HPH_GAIN_DSD_2, 0x01}, ++ {WCD938X_DIGITAL_CDC_AUX_GAIN_DSD_0, 0x00}, ++ {WCD938X_DIGITAL_CDC_AUX_GAIN_DSD_1, 0xFC}, ++ {WCD938X_DIGITAL_CDC_AUX_GAIN_DSD_2, 0x01}, ++ {WCD938X_DIGITAL_CDC_HPH_GAIN_CTL, 0x00}, ++ {WCD938X_DIGITAL_CDC_AUX_GAIN_CTL, 0x00}, ++ {WCD938X_DIGITAL_CDC_EAR_PATH_CTL, 0x00}, ++ {WCD938X_DIGITAL_CDC_SWR_CLH, 0x00}, ++ {WCD938X_DIGITAL_SWR_CLH_BYP, 0x00}, ++ {WCD938X_DIGITAL_CDC_TX0_CTL, 0x68}, ++ {WCD938X_DIGITAL_CDC_TX1_CTL, 0x68}, ++ {WCD938X_DIGITAL_CDC_TX2_CTL, 0x68}, ++ {WCD938X_DIGITAL_CDC_TX_RST, 0x00}, ++ {WCD938X_DIGITAL_CDC_REQ_CTL, 0x01}, ++ {WCD938X_DIGITAL_CDC_RST, 0x00}, ++ {WCD938X_DIGITAL_CDC_AMIC_CTL, 0x0F}, ++ {WCD938X_DIGITAL_CDC_DMIC_CTL, 0x04}, ++ {WCD938X_DIGITAL_CDC_DMIC1_CTL, 0x01}, ++ {WCD938X_DIGITAL_CDC_DMIC2_CTL, 0x01}, ++ {WCD938X_DIGITAL_CDC_DMIC3_CTL, 0x01}, ++ {WCD938X_DIGITAL_CDC_DMIC4_CTL, 0x01}, ++ {WCD938X_DIGITAL_EFUSE_PRG_CTL, 0x00}, ++ {WCD938X_DIGITAL_EFUSE_CTL, 0x2B}, ++ {WCD938X_DIGITAL_CDC_DMIC_RATE_1_2, 0x11}, ++ {WCD938X_DIGITAL_CDC_DMIC_RATE_3_4, 0x11}, ++ {WCD938X_DIGITAL_PDM_WD_CTL0, 0x00}, ++ {WCD938X_DIGITAL_PDM_WD_CTL1, 0x00}, ++ {WCD938X_DIGITAL_PDM_WD_CTL2, 0x00}, ++ {WCD938X_DIGITAL_INTR_MODE, 0x00}, ++ {WCD938X_DIGITAL_INTR_MASK_0, 0xFF}, ++ {WCD938X_DIGITAL_INTR_MASK_1, 0xFF}, ++ {WCD938X_DIGITAL_INTR_MASK_2, 0x3F}, ++ {WCD938X_DIGITAL_INTR_STATUS_0, 0x00}, ++ {WCD938X_DIGITAL_INTR_STATUS_1, 0x00}, ++ {WCD938X_DIGITAL_INTR_STATUS_2, 0x00}, ++ {WCD938X_DIGITAL_INTR_CLEAR_0, 0x00}, ++ {WCD938X_DIGITAL_INTR_CLEAR_1, 0x00}, ++ {WCD938X_DIGITAL_INTR_CLEAR_2, 0x00}, ++ {WCD938X_DIGITAL_INTR_LEVEL_0, 0x00}, ++ {WCD938X_DIGITAL_INTR_LEVEL_1, 0x00}, ++ {WCD938X_DIGITAL_INTR_LEVEL_2, 0x00}, ++ {WCD938X_DIGITAL_INTR_SET_0, 0x00}, ++ {WCD938X_DIGITAL_INTR_SET_1, 0x00}, ++ {WCD938X_DIGITAL_INTR_SET_2, 0x00}, ++ {WCD938X_DIGITAL_INTR_TEST_0, 0x00}, ++ {WCD938X_DIGITAL_INTR_TEST_1, 0x00}, ++ {WCD938X_DIGITAL_INTR_TEST_2, 0x00}, ++ {WCD938X_DIGITAL_TX_MODE_DBG_EN, 0x00}, ++ {WCD938X_DIGITAL_TX_MODE_DBG_0_1, 0x00}, ++ {WCD938X_DIGITAL_TX_MODE_DBG_2_3, 0x00}, ++ {WCD938X_DIGITAL_LB_IN_SEL_CTL, 0x00}, ++ {WCD938X_DIGITAL_LOOP_BACK_MODE, 0x00}, ++ {WCD938X_DIGITAL_SWR_DAC_TEST, 0x00}, ++ {WCD938X_DIGITAL_SWR_HM_TEST_RX_0, 0x40}, ++ {WCD938X_DIGITAL_SWR_HM_TEST_TX_0, 0x40}, ++ {WCD938X_DIGITAL_SWR_HM_TEST_RX_1, 0x00}, ++ {WCD938X_DIGITAL_SWR_HM_TEST_TX_1, 0x00}, ++ {WCD938X_DIGITAL_SWR_HM_TEST_TX_2, 0x00}, ++ {WCD938X_DIGITAL_SWR_HM_TEST_0, 0x00}, ++ {WCD938X_DIGITAL_SWR_HM_TEST_1, 0x00}, ++ {WCD938X_DIGITAL_PAD_CTL_SWR_0, 0x8F}, ++ {WCD938X_DIGITAL_PAD_CTL_SWR_1, 0x06}, ++ {WCD938X_DIGITAL_I2C_CTL, 0x00}, ++ {WCD938X_DIGITAL_CDC_TX_TANGGU_SW_MODE, 0x00}, ++ {WCD938X_DIGITAL_EFUSE_TEST_CTL_0, 0x00}, ++ {WCD938X_DIGITAL_EFUSE_TEST_CTL_1, 0x00}, ++ {WCD938X_DIGITAL_EFUSE_T_DATA_0, 0x00}, ++ {WCD938X_DIGITAL_EFUSE_T_DATA_1, 0x00}, ++ {WCD938X_DIGITAL_PAD_CTL_PDM_RX0, 0xF1}, ++ {WCD938X_DIGITAL_PAD_CTL_PDM_RX1, 0xF1}, ++ {WCD938X_DIGITAL_PAD_CTL_PDM_TX0, 0xF1}, ++ {WCD938X_DIGITAL_PAD_CTL_PDM_TX1, 0xF1}, ++ {WCD938X_DIGITAL_PAD_CTL_PDM_TX2, 0xF1}, ++ {WCD938X_DIGITAL_PAD_INP_DIS_0, 0x00}, ++ {WCD938X_DIGITAL_PAD_INP_DIS_1, 0x00}, ++ {WCD938X_DIGITAL_DRIVE_STRENGTH_0, 0x00}, ++ {WCD938X_DIGITAL_DRIVE_STRENGTH_1, 0x00}, ++ {WCD938X_DIGITAL_DRIVE_STRENGTH_2, 0x00}, ++ {WCD938X_DIGITAL_RX_DATA_EDGE_CTL, 0x1F}, ++ {WCD938X_DIGITAL_TX_DATA_EDGE_CTL, 0x80}, ++ {WCD938X_DIGITAL_GPIO_MODE, 0x00}, ++ {WCD938X_DIGITAL_PIN_CTL_OE, 0x00}, ++ {WCD938X_DIGITAL_PIN_CTL_DATA_0, 0x00}, ++ {WCD938X_DIGITAL_PIN_CTL_DATA_1, 0x00}, ++ {WCD938X_DIGITAL_PIN_STATUS_0, 0x00}, ++ {WCD938X_DIGITAL_PIN_STATUS_1, 0x00}, ++ {WCD938X_DIGITAL_DIG_DEBUG_CTL, 0x00}, ++ {WCD938X_DIGITAL_DIG_DEBUG_EN, 0x00}, ++ {WCD938X_DIGITAL_ANA_CSR_DBG_ADD, 0x00}, ++ {WCD938X_DIGITAL_ANA_CSR_DBG_CTL, 0x48}, ++ {WCD938X_DIGITAL_SSP_DBG, 0x00}, ++ {WCD938X_DIGITAL_MODE_STATUS_0, 0x00}, ++ {WCD938X_DIGITAL_MODE_STATUS_1, 0x00}, ++ {WCD938X_DIGITAL_SPARE_0, 0x00}, ++ {WCD938X_DIGITAL_SPARE_1, 0x00}, ++ {WCD938X_DIGITAL_SPARE_2, 0x00}, ++ {WCD938X_DIGITAL_EFUSE_REG_0, 0x00}, ++ {WCD938X_DIGITAL_EFUSE_REG_1, 0xFF}, ++ {WCD938X_DIGITAL_EFUSE_REG_2, 0xFF}, ++ {WCD938X_DIGITAL_EFUSE_REG_3, 0xFF}, ++ {WCD938X_DIGITAL_EFUSE_REG_4, 0xFF}, ++ {WCD938X_DIGITAL_EFUSE_REG_5, 0xFF}, ++ {WCD938X_DIGITAL_EFUSE_REG_6, 0xFF}, ++ {WCD938X_DIGITAL_EFUSE_REG_7, 0xFF}, ++ {WCD938X_DIGITAL_EFUSE_REG_8, 0xFF}, ++ {WCD938X_DIGITAL_EFUSE_REG_9, 0xFF}, ++ {WCD938X_DIGITAL_EFUSE_REG_10, 0xFF}, ++ {WCD938X_DIGITAL_EFUSE_REG_11, 0xFF}, ++ {WCD938X_DIGITAL_EFUSE_REG_12, 0xFF}, ++ {WCD938X_DIGITAL_EFUSE_REG_13, 0xFF}, ++ {WCD938X_DIGITAL_EFUSE_REG_14, 0xFF}, ++ {WCD938X_DIGITAL_EFUSE_REG_15, 0xFF}, ++ {WCD938X_DIGITAL_EFUSE_REG_16, 0xFF}, ++ {WCD938X_DIGITAL_EFUSE_REG_17, 0xFF}, ++ {WCD938X_DIGITAL_EFUSE_REG_18, 0xFF}, ++ {WCD938X_DIGITAL_EFUSE_REG_19, 0xFF}, ++ {WCD938X_DIGITAL_EFUSE_REG_20, 0x0E}, ++ {WCD938X_DIGITAL_EFUSE_REG_21, 0x00}, ++ {WCD938X_DIGITAL_EFUSE_REG_22, 0x00}, ++ {WCD938X_DIGITAL_EFUSE_REG_23, 0xF8}, ++ {WCD938X_DIGITAL_EFUSE_REG_24, 0x16}, ++ {WCD938X_DIGITAL_EFUSE_REG_25, 0x00}, ++ {WCD938X_DIGITAL_EFUSE_REG_26, 0x00}, ++ {WCD938X_DIGITAL_EFUSE_REG_27, 0x00}, ++ {WCD938X_DIGITAL_EFUSE_REG_28, 0x00}, ++ {WCD938X_DIGITAL_EFUSE_REG_29, 0x00}, ++ {WCD938X_DIGITAL_EFUSE_REG_30, 0x00}, ++ {WCD938X_DIGITAL_EFUSE_REG_31, 0x00}, ++ {WCD938X_DIGITAL_TX_REQ_FB_CTL_0, 0x88}, ++ {WCD938X_DIGITAL_TX_REQ_FB_CTL_1, 0x88}, ++ {WCD938X_DIGITAL_TX_REQ_FB_CTL_2, 0x88}, ++ {WCD938X_DIGITAL_TX_REQ_FB_CTL_3, 0x88}, ++ {WCD938X_DIGITAL_TX_REQ_FB_CTL_4, 0x88}, ++ {WCD938X_DIGITAL_DEM_BYPASS_DATA0, 0x55}, ++ {WCD938X_DIGITAL_DEM_BYPASS_DATA1, 0x55}, ++ {WCD938X_DIGITAL_DEM_BYPASS_DATA2, 0x55}, ++ {WCD938X_DIGITAL_DEM_BYPASS_DATA3, 0x01}, ++}; ++ ++static bool wcd938x_rdwr_register(struct device *dev, unsigned int reg) ++{ ++ switch (reg) { ++ case WCD938X_ANA_PAGE_REGISTER: ++ case WCD938X_ANA_BIAS: ++ case WCD938X_ANA_RX_SUPPLIES: ++ case WCD938X_ANA_HPH: ++ case WCD938X_ANA_EAR: ++ case WCD938X_ANA_EAR_COMPANDER_CTL: ++ case WCD938X_ANA_TX_CH1: ++ case WCD938X_ANA_TX_CH2: ++ case WCD938X_ANA_TX_CH3: ++ case WCD938X_ANA_TX_CH4: ++ case WCD938X_ANA_MICB1_MICB2_DSP_EN_LOGIC: ++ case WCD938X_ANA_MICB3_DSP_EN_LOGIC: ++ case WCD938X_ANA_MBHC_MECH: ++ case WCD938X_ANA_MBHC_ELECT: ++ case WCD938X_ANA_MBHC_ZDET: ++ case WCD938X_ANA_MBHC_BTN0: ++ case WCD938X_ANA_MBHC_BTN1: ++ case WCD938X_ANA_MBHC_BTN2: ++ case WCD938X_ANA_MBHC_BTN3: ++ case WCD938X_ANA_MBHC_BTN4: ++ case WCD938X_ANA_MBHC_BTN5: ++ case WCD938X_ANA_MBHC_BTN6: ++ case WCD938X_ANA_MBHC_BTN7: ++ case WCD938X_ANA_MICB1: ++ case WCD938X_ANA_MICB2: ++ case WCD938X_ANA_MICB2_RAMP: ++ case WCD938X_ANA_MICB3: ++ case WCD938X_ANA_MICB4: ++ case WCD938X_BIAS_CTL: ++ case WCD938X_BIAS_VBG_FINE_ADJ: ++ case WCD938X_LDOL_VDDCX_ADJUST: ++ case WCD938X_LDOL_DISABLE_LDOL: ++ case WCD938X_MBHC_CTL_CLK: ++ case WCD938X_MBHC_CTL_ANA: ++ case WCD938X_MBHC_CTL_SPARE_1: ++ case WCD938X_MBHC_CTL_SPARE_2: ++ case WCD938X_MBHC_CTL_BCS: ++ case WCD938X_MBHC_TEST_CTL: ++ case WCD938X_LDOH_MODE: ++ case WCD938X_LDOH_BIAS: ++ case WCD938X_LDOH_STB_LOADS: ++ case WCD938X_LDOH_SLOWRAMP: ++ case WCD938X_MICB1_TEST_CTL_1: ++ case WCD938X_MICB1_TEST_CTL_2: ++ case WCD938X_MICB1_TEST_CTL_3: ++ case WCD938X_MICB2_TEST_CTL_1: ++ case WCD938X_MICB2_TEST_CTL_2: ++ case WCD938X_MICB2_TEST_CTL_3: ++ case WCD938X_MICB3_TEST_CTL_1: ++ case WCD938X_MICB3_TEST_CTL_2: ++ case WCD938X_MICB3_TEST_CTL_3: ++ case WCD938X_MICB4_TEST_CTL_1: ++ case WCD938X_MICB4_TEST_CTL_2: ++ case WCD938X_MICB4_TEST_CTL_3: ++ case WCD938X_TX_COM_ADC_VCM: ++ case WCD938X_TX_COM_BIAS_ATEST: ++ case WCD938X_TX_COM_SPARE1: ++ case WCD938X_TX_COM_SPARE2: ++ case WCD938X_TX_COM_TXFE_DIV_CTL: ++ case WCD938X_TX_COM_TXFE_DIV_START: ++ case WCD938X_TX_COM_SPARE3: ++ case WCD938X_TX_COM_SPARE4: ++ case WCD938X_TX_1_2_TEST_EN: ++ case WCD938X_TX_1_2_ADC_IB: ++ case WCD938X_TX_1_2_ATEST_REFCTL: ++ case WCD938X_TX_1_2_TEST_CTL: ++ case WCD938X_TX_1_2_TEST_BLK_EN1: ++ case WCD938X_TX_1_2_TXFE1_CLKDIV: ++ case WCD938X_TX_3_4_TEST_EN: ++ case WCD938X_TX_3_4_ADC_IB: ++ case WCD938X_TX_3_4_ATEST_REFCTL: ++ case WCD938X_TX_3_4_TEST_CTL: ++ case WCD938X_TX_3_4_TEST_BLK_EN3: ++ case WCD938X_TX_3_4_TXFE3_CLKDIV: ++ case WCD938X_TX_3_4_TEST_BLK_EN2: ++ case WCD938X_TX_3_4_TXFE2_CLKDIV: ++ case WCD938X_TX_3_4_SPARE1: ++ case WCD938X_TX_3_4_TEST_BLK_EN4: ++ case WCD938X_TX_3_4_TXFE4_CLKDIV: ++ case WCD938X_TX_3_4_SPARE2: ++ case WCD938X_CLASSH_MODE_1: ++ case WCD938X_CLASSH_MODE_2: ++ case WCD938X_CLASSH_MODE_3: ++ case WCD938X_CLASSH_CTRL_VCL_1: ++ case WCD938X_CLASSH_CTRL_VCL_2: ++ case WCD938X_CLASSH_CTRL_CCL_1: ++ case WCD938X_CLASSH_CTRL_CCL_2: ++ case WCD938X_CLASSH_CTRL_CCL_3: ++ case WCD938X_CLASSH_CTRL_CCL_4: ++ case WCD938X_CLASSH_CTRL_CCL_5: ++ case WCD938X_CLASSH_BUCK_TMUX_A_D: ++ case WCD938X_CLASSH_BUCK_SW_DRV_CNTL: ++ case WCD938X_CLASSH_SPARE: ++ case WCD938X_FLYBACK_EN: ++ case WCD938X_FLYBACK_VNEG_CTRL_1: ++ case WCD938X_FLYBACK_VNEG_CTRL_2: ++ case WCD938X_FLYBACK_VNEG_CTRL_3: ++ case WCD938X_FLYBACK_VNEG_CTRL_4: ++ case WCD938X_FLYBACK_VNEG_CTRL_5: ++ case WCD938X_FLYBACK_VNEG_CTRL_6: ++ case WCD938X_FLYBACK_VNEG_CTRL_7: ++ case WCD938X_FLYBACK_VNEG_CTRL_8: ++ case WCD938X_FLYBACK_VNEG_CTRL_9: ++ case WCD938X_FLYBACK_VNEGDAC_CTRL_1: ++ case WCD938X_FLYBACK_VNEGDAC_CTRL_2: ++ case WCD938X_FLYBACK_VNEGDAC_CTRL_3: ++ case WCD938X_FLYBACK_CTRL_1: ++ case WCD938X_FLYBACK_TEST_CTL: ++ case WCD938X_RX_AUX_SW_CTL: ++ case WCD938X_RX_PA_AUX_IN_CONN: ++ case WCD938X_RX_TIMER_DIV: ++ case WCD938X_RX_OCP_CTL: ++ case WCD938X_RX_OCP_COUNT: ++ case WCD938X_RX_BIAS_EAR_DAC: ++ case WCD938X_RX_BIAS_EAR_AMP: ++ case WCD938X_RX_BIAS_HPH_LDO: ++ case WCD938X_RX_BIAS_HPH_PA: ++ case WCD938X_RX_BIAS_HPH_RDACBUFF_CNP2: ++ case WCD938X_RX_BIAS_HPH_RDAC_LDO: ++ case WCD938X_RX_BIAS_HPH_CNP1: ++ case WCD938X_RX_BIAS_HPH_LOWPOWER: ++ case WCD938X_RX_BIAS_AUX_DAC: ++ case WCD938X_RX_BIAS_AUX_AMP: ++ case WCD938X_RX_BIAS_VNEGDAC_BLEEDER: ++ case WCD938X_RX_BIAS_MISC: ++ case WCD938X_RX_BIAS_BUCK_RST: ++ case WCD938X_RX_BIAS_BUCK_VREF_ERRAMP: ++ case WCD938X_RX_BIAS_FLYB_ERRAMP: ++ case WCD938X_RX_BIAS_FLYB_BUFF: ++ case WCD938X_RX_BIAS_FLYB_MID_RST: ++ case WCD938X_HPH_CNP_EN: ++ case WCD938X_HPH_CNP_WG_CTL: ++ case WCD938X_HPH_CNP_WG_TIME: ++ case WCD938X_HPH_OCP_CTL: ++ case WCD938X_HPH_AUTO_CHOP: ++ case WCD938X_HPH_CHOP_CTL: ++ case WCD938X_HPH_PA_CTL1: ++ case WCD938X_HPH_PA_CTL2: ++ case WCD938X_HPH_L_EN: ++ case WCD938X_HPH_L_TEST: ++ case WCD938X_HPH_L_ATEST: ++ case WCD938X_HPH_R_EN: ++ case WCD938X_HPH_R_TEST: ++ case WCD938X_HPH_R_ATEST: ++ case WCD938X_HPH_RDAC_CLK_CTL1: ++ case WCD938X_HPH_RDAC_CLK_CTL2: ++ case WCD938X_HPH_RDAC_LDO_CTL: ++ case WCD938X_HPH_RDAC_CHOP_CLK_LP_CTL: ++ case WCD938X_HPH_REFBUFF_UHQA_CTL: ++ case WCD938X_HPH_REFBUFF_LP_CTL: ++ case WCD938X_HPH_L_DAC_CTL: ++ case WCD938X_HPH_R_DAC_CTL: ++ case WCD938X_HPH_SURGE_HPHLR_SURGE_COMP_SEL: ++ case WCD938X_HPH_SURGE_HPHLR_SURGE_EN: ++ case WCD938X_HPH_SURGE_HPHLR_SURGE_MISC1: ++ case WCD938X_EAR_EAR_EN_REG: ++ case WCD938X_EAR_EAR_PA_CON: ++ case WCD938X_EAR_EAR_SP_CON: ++ case WCD938X_EAR_EAR_DAC_CON: ++ case WCD938X_EAR_EAR_CNP_FSM_CON: ++ case WCD938X_EAR_TEST_CTL: ++ case WCD938X_ANA_NEW_PAGE_REGISTER: ++ case WCD938X_HPH_NEW_ANA_HPH2: ++ case WCD938X_HPH_NEW_ANA_HPH3: ++ case WCD938X_SLEEP_CTL: ++ case WCD938X_SLEEP_WATCHDOG_CTL: ++ case WCD938X_MBHC_NEW_ELECT_REM_CLAMP_CTL: ++ case WCD938X_MBHC_NEW_CTL_1: ++ case WCD938X_MBHC_NEW_CTL_2: ++ case WCD938X_MBHC_NEW_PLUG_DETECT_CTL: ++ case WCD938X_MBHC_NEW_ZDET_ANA_CTL: ++ case WCD938X_MBHC_NEW_ZDET_RAMP_CTL: ++ case WCD938X_TX_NEW_AMIC_MUX_CFG: ++ case WCD938X_AUX_AUXPA: ++ case WCD938X_LDORXTX_MODE: ++ case WCD938X_LDORXTX_CONFIG: ++ case WCD938X_DIE_CRACK_DIE_CRK_DET_EN: ++ case WCD938X_HPH_NEW_INT_RDAC_GAIN_CTL: ++ case WCD938X_HPH_NEW_INT_RDAC_HD2_CTL_L: ++ case WCD938X_HPH_NEW_INT_RDAC_VREF_CTL: ++ case WCD938X_HPH_NEW_INT_RDAC_OVERRIDE_CTL: ++ case WCD938X_HPH_NEW_INT_RDAC_HD2_CTL_R: ++ case WCD938X_HPH_NEW_INT_PA_MISC1: ++ case WCD938X_HPH_NEW_INT_PA_MISC2: ++ case WCD938X_HPH_NEW_INT_PA_RDAC_MISC: ++ case WCD938X_HPH_NEW_INT_HPH_TIMER1: ++ case WCD938X_HPH_NEW_INT_HPH_TIMER2: ++ case WCD938X_HPH_NEW_INT_HPH_TIMER3: ++ case WCD938X_HPH_NEW_INT_HPH_TIMER4: ++ case WCD938X_HPH_NEW_INT_PA_RDAC_MISC2: ++ case WCD938X_HPH_NEW_INT_PA_RDAC_MISC3: ++ case WCD938X_HPH_NEW_INT_RDAC_HD2_CTL_L_NEW: ++ case WCD938X_HPH_NEW_INT_RDAC_HD2_CTL_R_NEW: ++ case WCD938X_RX_NEW_INT_HPH_RDAC_BIAS_LOHIFI: ++ case WCD938X_RX_NEW_INT_HPH_RDAC_BIAS_ULP: ++ case WCD938X_RX_NEW_INT_HPH_RDAC_LDO_LP: ++ case WCD938X_MBHC_NEW_INT_MOISTURE_DET_DC_CTRL: ++ case WCD938X_MBHC_NEW_INT_MOISTURE_DET_POLLING_CTRL: ++ case WCD938X_MBHC_NEW_INT_MECH_DET_CURRENT: ++ case WCD938X_MBHC_NEW_INT_SPARE_2: ++ case WCD938X_EAR_INT_NEW_EAR_CHOPPER_CON: ++ case WCD938X_EAR_INT_NEW_CNP_VCM_CON1: ++ case WCD938X_EAR_INT_NEW_CNP_VCM_CON2: ++ case WCD938X_EAR_INT_NEW_EAR_DYNAMIC_BIAS: ++ case WCD938X_AUX_INT_EN_REG: ++ case WCD938X_AUX_INT_PA_CTRL: ++ case WCD938X_AUX_INT_SP_CTRL: ++ case WCD938X_AUX_INT_DAC_CTRL: ++ case WCD938X_AUX_INT_CLK_CTRL: ++ case WCD938X_AUX_INT_TEST_CTRL: ++ case WCD938X_AUX_INT_MISC: ++ case WCD938X_LDORXTX_INT_BIAS: ++ case WCD938X_LDORXTX_INT_STB_LOADS_DTEST: ++ case WCD938X_LDORXTX_INT_TEST0: ++ case WCD938X_LDORXTX_INT_STARTUP_TIMER: ++ case WCD938X_LDORXTX_INT_TEST1: ++ case WCD938X_SLEEP_INT_WATCHDOG_CTL_1: ++ case WCD938X_SLEEP_INT_WATCHDOG_CTL_2: ++ case WCD938X_DIE_CRACK_INT_DIE_CRK_DET_INT1: ++ case WCD938X_DIE_CRACK_INT_DIE_CRK_DET_INT2: ++ case WCD938X_TX_COM_NEW_INT_TXFE_DIVSTOP_L2: ++ case WCD938X_TX_COM_NEW_INT_TXFE_DIVSTOP_L1: ++ case WCD938X_TX_COM_NEW_INT_TXFE_DIVSTOP_L0: ++ case WCD938X_TX_COM_NEW_INT_TXFE_DIVSTOP_ULP1P2M: ++ case WCD938X_TX_COM_NEW_INT_TXFE_DIVSTOP_ULP0P6M: ++ case WCD938X_TX_COM_NEW_INT_TXFE_ICTRL_STG1_L2L1: ++ case WCD938X_TX_COM_NEW_INT_TXFE_ICTRL_STG1_L0: ++ case WCD938X_TX_COM_NEW_INT_TXFE_ICTRL_STG1_ULP: ++ case WCD938X_TX_COM_NEW_INT_TXFE_ICTRL_STG2MAIN_L2L1: ++ case WCD938X_TX_COM_NEW_INT_TXFE_ICTRL_STG2MAIN_L0: ++ case WCD938X_TX_COM_NEW_INT_TXFE_ICTRL_STG2MAIN_ULP: ++ case WCD938X_TX_COM_NEW_INT_TXFE_ICTRL_STG2CASC_L2L1L0: ++ case WCD938X_TX_COM_NEW_INT_TXFE_ICTRL_STG2CASC_ULP: ++ case WCD938X_TX_COM_NEW_INT_TXADC_SCBIAS_L2L1: ++ case WCD938X_TX_COM_NEW_INT_TXADC_SCBIAS_L0ULP: ++ case WCD938X_TX_COM_NEW_INT_TXADC_INT_L2: ++ case WCD938X_TX_COM_NEW_INT_TXADC_INT_L1: ++ case WCD938X_TX_COM_NEW_INT_TXADC_INT_L0: ++ case WCD938X_TX_COM_NEW_INT_TXADC_INT_ULP: ++ case WCD938X_DIGITAL_PAGE_REGISTER: ++ case WCD938X_DIGITAL_SWR_TX_CLK_RATE: ++ case WCD938X_DIGITAL_CDC_RST_CTL: ++ case WCD938X_DIGITAL_TOP_CLK_CFG: ++ case WCD938X_DIGITAL_CDC_ANA_CLK_CTL: ++ case WCD938X_DIGITAL_CDC_DIG_CLK_CTL: ++ case WCD938X_DIGITAL_SWR_RST_EN: ++ case WCD938X_DIGITAL_CDC_PATH_MODE: ++ case WCD938X_DIGITAL_CDC_RX_RST: ++ case WCD938X_DIGITAL_CDC_RX0_CTL: ++ case WCD938X_DIGITAL_CDC_RX1_CTL: ++ case WCD938X_DIGITAL_CDC_RX2_CTL: ++ case WCD938X_DIGITAL_CDC_TX_ANA_MODE_0_1: ++ case WCD938X_DIGITAL_CDC_TX_ANA_MODE_2_3: ++ case WCD938X_DIGITAL_CDC_COMP_CTL_0: ++ case WCD938X_DIGITAL_CDC_ANA_TX_CLK_CTL: ++ case WCD938X_DIGITAL_CDC_HPH_DSM_A1_0: ++ case WCD938X_DIGITAL_CDC_HPH_DSM_A1_1: ++ case WCD938X_DIGITAL_CDC_HPH_DSM_A2_0: ++ case WCD938X_DIGITAL_CDC_HPH_DSM_A2_1: ++ case WCD938X_DIGITAL_CDC_HPH_DSM_A3_0: ++ case WCD938X_DIGITAL_CDC_HPH_DSM_A3_1: ++ case WCD938X_DIGITAL_CDC_HPH_DSM_A4_0: ++ case WCD938X_DIGITAL_CDC_HPH_DSM_A4_1: ++ case WCD938X_DIGITAL_CDC_HPH_DSM_A5_0: ++ case WCD938X_DIGITAL_CDC_HPH_DSM_A5_1: ++ case WCD938X_DIGITAL_CDC_HPH_DSM_A6_0: ++ case WCD938X_DIGITAL_CDC_HPH_DSM_A7_0: ++ case WCD938X_DIGITAL_CDC_HPH_DSM_C_0: ++ case WCD938X_DIGITAL_CDC_HPH_DSM_C_1: ++ case WCD938X_DIGITAL_CDC_HPH_DSM_C_2: ++ case WCD938X_DIGITAL_CDC_HPH_DSM_C_3: ++ case WCD938X_DIGITAL_CDC_HPH_DSM_R1: ++ case WCD938X_DIGITAL_CDC_HPH_DSM_R2: ++ case WCD938X_DIGITAL_CDC_HPH_DSM_R3: ++ case WCD938X_DIGITAL_CDC_HPH_DSM_R4: ++ case WCD938X_DIGITAL_CDC_HPH_DSM_R5: ++ case WCD938X_DIGITAL_CDC_HPH_DSM_R6: ++ case WCD938X_DIGITAL_CDC_HPH_DSM_R7: ++ case WCD938X_DIGITAL_CDC_AUX_DSM_A1_0: ++ case WCD938X_DIGITAL_CDC_AUX_DSM_A1_1: ++ case WCD938X_DIGITAL_CDC_AUX_DSM_A2_0: ++ case WCD938X_DIGITAL_CDC_AUX_DSM_A2_1: ++ case WCD938X_DIGITAL_CDC_AUX_DSM_A3_0: ++ case WCD938X_DIGITAL_CDC_AUX_DSM_A3_1: ++ case WCD938X_DIGITAL_CDC_AUX_DSM_A4_0: ++ case WCD938X_DIGITAL_CDC_AUX_DSM_A4_1: ++ case WCD938X_DIGITAL_CDC_AUX_DSM_A5_0: ++ case WCD938X_DIGITAL_CDC_AUX_DSM_A5_1: ++ case WCD938X_DIGITAL_CDC_AUX_DSM_A6_0: ++ case WCD938X_DIGITAL_CDC_AUX_DSM_A7_0: ++ case WCD938X_DIGITAL_CDC_AUX_DSM_C_0: ++ case WCD938X_DIGITAL_CDC_AUX_DSM_C_1: ++ case WCD938X_DIGITAL_CDC_AUX_DSM_C_2: ++ case WCD938X_DIGITAL_CDC_AUX_DSM_C_3: ++ case WCD938X_DIGITAL_CDC_AUX_DSM_R1: ++ case WCD938X_DIGITAL_CDC_AUX_DSM_R2: ++ case WCD938X_DIGITAL_CDC_AUX_DSM_R3: ++ case WCD938X_DIGITAL_CDC_AUX_DSM_R4: ++ case WCD938X_DIGITAL_CDC_AUX_DSM_R5: ++ case WCD938X_DIGITAL_CDC_AUX_DSM_R6: ++ case WCD938X_DIGITAL_CDC_AUX_DSM_R7: ++ case WCD938X_DIGITAL_CDC_HPH_GAIN_RX_0: ++ case WCD938X_DIGITAL_CDC_HPH_GAIN_RX_1: ++ case WCD938X_DIGITAL_CDC_HPH_GAIN_DSD_0: ++ case WCD938X_DIGITAL_CDC_HPH_GAIN_DSD_1: ++ case WCD938X_DIGITAL_CDC_HPH_GAIN_DSD_2: ++ case WCD938X_DIGITAL_CDC_AUX_GAIN_DSD_0: ++ case WCD938X_DIGITAL_CDC_AUX_GAIN_DSD_1: ++ case WCD938X_DIGITAL_CDC_AUX_GAIN_DSD_2: ++ case WCD938X_DIGITAL_CDC_HPH_GAIN_CTL: ++ case WCD938X_DIGITAL_CDC_AUX_GAIN_CTL: ++ case WCD938X_DIGITAL_CDC_EAR_PATH_CTL: ++ case WCD938X_DIGITAL_CDC_SWR_CLH: ++ case WCD938X_DIGITAL_SWR_CLH_BYP: ++ case WCD938X_DIGITAL_CDC_TX0_CTL: ++ case WCD938X_DIGITAL_CDC_TX1_CTL: ++ case WCD938X_DIGITAL_CDC_TX2_CTL: ++ case WCD938X_DIGITAL_CDC_TX_RST: ++ case WCD938X_DIGITAL_CDC_REQ_CTL: ++ case WCD938X_DIGITAL_CDC_RST: ++ case WCD938X_DIGITAL_CDC_AMIC_CTL: ++ case WCD938X_DIGITAL_CDC_DMIC_CTL: ++ case WCD938X_DIGITAL_CDC_DMIC1_CTL: ++ case WCD938X_DIGITAL_CDC_DMIC2_CTL: ++ case WCD938X_DIGITAL_CDC_DMIC3_CTL: ++ case WCD938X_DIGITAL_CDC_DMIC4_CTL: ++ case WCD938X_DIGITAL_EFUSE_PRG_CTL: ++ case WCD938X_DIGITAL_EFUSE_CTL: ++ case WCD938X_DIGITAL_CDC_DMIC_RATE_1_2: ++ case WCD938X_DIGITAL_CDC_DMIC_RATE_3_4: ++ case WCD938X_DIGITAL_PDM_WD_CTL0: ++ case WCD938X_DIGITAL_PDM_WD_CTL1: ++ case WCD938X_DIGITAL_PDM_WD_CTL2: ++ case WCD938X_DIGITAL_INTR_MODE: ++ case WCD938X_DIGITAL_INTR_MASK_0: ++ case WCD938X_DIGITAL_INTR_MASK_1: ++ case WCD938X_DIGITAL_INTR_MASK_2: ++ case WCD938X_DIGITAL_INTR_CLEAR_0: ++ case WCD938X_DIGITAL_INTR_CLEAR_1: ++ case WCD938X_DIGITAL_INTR_CLEAR_2: ++ case WCD938X_DIGITAL_INTR_LEVEL_0: ++ case WCD938X_DIGITAL_INTR_LEVEL_1: ++ case WCD938X_DIGITAL_INTR_LEVEL_2: ++ case WCD938X_DIGITAL_INTR_SET_0: ++ case WCD938X_DIGITAL_INTR_SET_1: ++ case WCD938X_DIGITAL_INTR_SET_2: ++ case WCD938X_DIGITAL_INTR_TEST_0: ++ case WCD938X_DIGITAL_INTR_TEST_1: ++ case WCD938X_DIGITAL_INTR_TEST_2: ++ case WCD938X_DIGITAL_TX_MODE_DBG_EN: ++ case WCD938X_DIGITAL_TX_MODE_DBG_0_1: ++ case WCD938X_DIGITAL_TX_MODE_DBG_2_3: ++ case WCD938X_DIGITAL_LB_IN_SEL_CTL: ++ case WCD938X_DIGITAL_LOOP_BACK_MODE: ++ case WCD938X_DIGITAL_SWR_DAC_TEST: ++ case WCD938X_DIGITAL_SWR_HM_TEST_RX_0: ++ case WCD938X_DIGITAL_SWR_HM_TEST_TX_0: ++ case WCD938X_DIGITAL_SWR_HM_TEST_RX_1: ++ case WCD938X_DIGITAL_SWR_HM_TEST_TX_1: ++ case WCD938X_DIGITAL_SWR_HM_TEST_TX_2: ++ case WCD938X_DIGITAL_PAD_CTL_SWR_0: ++ case WCD938X_DIGITAL_PAD_CTL_SWR_1: ++ case WCD938X_DIGITAL_I2C_CTL: ++ case WCD938X_DIGITAL_CDC_TX_TANGGU_SW_MODE: ++ case WCD938X_DIGITAL_EFUSE_TEST_CTL_0: ++ case WCD938X_DIGITAL_EFUSE_TEST_CTL_1: ++ case WCD938X_DIGITAL_PAD_CTL_PDM_RX0: ++ case WCD938X_DIGITAL_PAD_CTL_PDM_RX1: ++ case WCD938X_DIGITAL_PAD_CTL_PDM_TX0: ++ case WCD938X_DIGITAL_PAD_CTL_PDM_TX1: ++ case WCD938X_DIGITAL_PAD_CTL_PDM_TX2: ++ case WCD938X_DIGITAL_PAD_INP_DIS_0: ++ case WCD938X_DIGITAL_PAD_INP_DIS_1: ++ case WCD938X_DIGITAL_DRIVE_STRENGTH_0: ++ case WCD938X_DIGITAL_DRIVE_STRENGTH_1: ++ case WCD938X_DIGITAL_DRIVE_STRENGTH_2: ++ case WCD938X_DIGITAL_RX_DATA_EDGE_CTL: ++ case WCD938X_DIGITAL_TX_DATA_EDGE_CTL: ++ case WCD938X_DIGITAL_GPIO_MODE: ++ case WCD938X_DIGITAL_PIN_CTL_OE: ++ case WCD938X_DIGITAL_PIN_CTL_DATA_0: ++ case WCD938X_DIGITAL_PIN_CTL_DATA_1: ++ case WCD938X_DIGITAL_DIG_DEBUG_CTL: ++ case WCD938X_DIGITAL_DIG_DEBUG_EN: ++ case WCD938X_DIGITAL_ANA_CSR_DBG_ADD: ++ case WCD938X_DIGITAL_ANA_CSR_DBG_CTL: ++ case WCD938X_DIGITAL_SSP_DBG: ++ case WCD938X_DIGITAL_SPARE_0: ++ case WCD938X_DIGITAL_SPARE_1: ++ case WCD938X_DIGITAL_SPARE_2: ++ case WCD938X_DIGITAL_TX_REQ_FB_CTL_0: ++ case WCD938X_DIGITAL_TX_REQ_FB_CTL_1: ++ case WCD938X_DIGITAL_TX_REQ_FB_CTL_2: ++ case WCD938X_DIGITAL_TX_REQ_FB_CTL_3: ++ case WCD938X_DIGITAL_TX_REQ_FB_CTL_4: ++ case WCD938X_DIGITAL_DEM_BYPASS_DATA0: ++ case WCD938X_DIGITAL_DEM_BYPASS_DATA1: ++ case WCD938X_DIGITAL_DEM_BYPASS_DATA2: ++ case WCD938X_DIGITAL_DEM_BYPASS_DATA3: ++ return true; ++ } ++ ++ return false; ++} ++ ++static bool wcd938x_readonly_register(struct device *dev, unsigned int reg) ++{ ++ switch (reg) { ++ case WCD938X_ANA_MBHC_RESULT_1: ++ case WCD938X_ANA_MBHC_RESULT_2: ++ case WCD938X_ANA_MBHC_RESULT_3: ++ case WCD938X_MBHC_MOISTURE_DET_FSM_STATUS: ++ case WCD938X_TX_1_2_SAR2_ERR: ++ case WCD938X_TX_1_2_SAR1_ERR: ++ case WCD938X_TX_3_4_SAR4_ERR: ++ case WCD938X_TX_3_4_SAR3_ERR: ++ case WCD938X_HPH_L_STATUS: ++ case WCD938X_HPH_R_STATUS: ++ case WCD938X_HPH_SURGE_HPHLR_SURGE_STATUS: ++ case WCD938X_EAR_STATUS_REG_1: ++ case WCD938X_EAR_STATUS_REG_2: ++ case WCD938X_MBHC_NEW_FSM_STATUS: ++ case WCD938X_MBHC_NEW_ADC_RESULT: ++ case WCD938X_DIE_CRACK_DIE_CRK_DET_OUT: ++ case WCD938X_AUX_INT_STATUS_REG: ++ case WCD938X_LDORXTX_INT_STATUS: ++ case WCD938X_DIGITAL_CHIP_ID0: ++ case WCD938X_DIGITAL_CHIP_ID1: ++ case WCD938X_DIGITAL_CHIP_ID2: ++ case WCD938X_DIGITAL_CHIP_ID3: ++ case WCD938X_DIGITAL_INTR_STATUS_0: ++ case WCD938X_DIGITAL_INTR_STATUS_1: ++ case WCD938X_DIGITAL_INTR_STATUS_2: ++ case WCD938X_DIGITAL_INTR_CLEAR_0: ++ case WCD938X_DIGITAL_INTR_CLEAR_1: ++ case WCD938X_DIGITAL_INTR_CLEAR_2: ++ case WCD938X_DIGITAL_SWR_HM_TEST_0: ++ case WCD938X_DIGITAL_SWR_HM_TEST_1: ++ case WCD938X_DIGITAL_EFUSE_T_DATA_0: ++ case WCD938X_DIGITAL_EFUSE_T_DATA_1: ++ case WCD938X_DIGITAL_PIN_STATUS_0: ++ case WCD938X_DIGITAL_PIN_STATUS_1: ++ case WCD938X_DIGITAL_MODE_STATUS_0: ++ case WCD938X_DIGITAL_MODE_STATUS_1: ++ case WCD938X_DIGITAL_EFUSE_REG_0: ++ case WCD938X_DIGITAL_EFUSE_REG_1: ++ case WCD938X_DIGITAL_EFUSE_REG_2: ++ case WCD938X_DIGITAL_EFUSE_REG_3: ++ case WCD938X_DIGITAL_EFUSE_REG_4: ++ case WCD938X_DIGITAL_EFUSE_REG_5: ++ case WCD938X_DIGITAL_EFUSE_REG_6: ++ case WCD938X_DIGITAL_EFUSE_REG_7: ++ case WCD938X_DIGITAL_EFUSE_REG_8: ++ case WCD938X_DIGITAL_EFUSE_REG_9: ++ case WCD938X_DIGITAL_EFUSE_REG_10: ++ case WCD938X_DIGITAL_EFUSE_REG_11: ++ case WCD938X_DIGITAL_EFUSE_REG_12: ++ case WCD938X_DIGITAL_EFUSE_REG_13: ++ case WCD938X_DIGITAL_EFUSE_REG_14: ++ case WCD938X_DIGITAL_EFUSE_REG_15: ++ case WCD938X_DIGITAL_EFUSE_REG_16: ++ case WCD938X_DIGITAL_EFUSE_REG_17: ++ case WCD938X_DIGITAL_EFUSE_REG_18: ++ case WCD938X_DIGITAL_EFUSE_REG_19: ++ case WCD938X_DIGITAL_EFUSE_REG_20: ++ case WCD938X_DIGITAL_EFUSE_REG_21: ++ case WCD938X_DIGITAL_EFUSE_REG_22: ++ case WCD938X_DIGITAL_EFUSE_REG_23: ++ case WCD938X_DIGITAL_EFUSE_REG_24: ++ case WCD938X_DIGITAL_EFUSE_REG_25: ++ case WCD938X_DIGITAL_EFUSE_REG_26: ++ case WCD938X_DIGITAL_EFUSE_REG_27: ++ case WCD938X_DIGITAL_EFUSE_REG_28: ++ case WCD938X_DIGITAL_EFUSE_REG_29: ++ case WCD938X_DIGITAL_EFUSE_REG_30: ++ case WCD938X_DIGITAL_EFUSE_REG_31: ++ return true; ++ } ++ return false; ++} ++ ++static bool wcd938x_readable_register(struct device *dev, unsigned int reg) ++{ ++ bool ret; ++ ++ ret = wcd938x_readonly_register(dev, reg); ++ if (!ret) ++ return wcd938x_rdwr_register(dev, reg); ++ ++ return ret; ++} ++ ++static bool wcd938x_writeable_register(struct device *dev, unsigned int reg) ++{ ++ return wcd938x_rdwr_register(dev, reg); ++} ++ ++static bool wcd938x_volatile_register(struct device *dev, unsigned int reg) ++{ ++ if (reg <= WCD938X_BASE_ADDRESS) ++ return false; ++ ++ if (reg == WCD938X_DIGITAL_SWR_TX_CLK_RATE) ++ return true; ++ ++ if (wcd938x_readonly_register(dev, reg)) ++ return true; ++ ++ return false; ++} ++ ++static const struct regmap_config wcd938x_regmap_config = { ++ .name = "wcd938x_csr", ++ .reg_bits = 32, ++ .val_bits = 8, ++ .cache_type = REGCACHE_RBTREE, ++ .reg_defaults = wcd938x_defaults, ++ .num_reg_defaults = ARRAY_SIZE(wcd938x_defaults), ++ .max_register = WCD938X_MAX_REGISTER, ++ .readable_reg = wcd938x_readable_register, ++ .writeable_reg = wcd938x_writeable_register, ++ .volatile_reg = wcd938x_volatile_register, ++ .can_multi_write = true, ++}; ++ + static const struct sdw_slave_ops wcd9380_slave_ops = { + .update_status = wcd9380_update_status, + .interrupt_callback = wcd9380_interrupt_callback, +@@ -260,6 +1262,16 @@ static int wcd9380_probe(struct sdw_slave *pdev, + wcd->ch_info = &wcd938x_sdw_rx_ch_info[0]; + } + ++ if (wcd->is_tx) { ++ wcd->regmap = devm_regmap_init_sdw(pdev, &wcd938x_regmap_config); ++ if (IS_ERR(wcd->regmap)) ++ return dev_err_probe(dev, PTR_ERR(wcd->regmap), ++ "Regmap init failed\n"); ++ ++ /* Start in cache-only until device is enumerated */ ++ regcache_cache_only(wcd->regmap, true); ++ }; ++ + pm_runtime_set_autosuspend_delay(dev, 3000); + pm_runtime_use_autosuspend(dev); + pm_runtime_mark_last_busy(dev); +@@ -301,22 +1313,23 @@ MODULE_DEVICE_TABLE(sdw, wcd9380_slave_id); + + static int __maybe_unused wcd938x_sdw_runtime_suspend(struct device *dev) + { +- struct regmap *regmap = dev_get_regmap(dev, NULL); ++ struct wcd938x_sdw_priv *wcd = dev_get_drvdata(dev); + +- if (regmap) { +- regcache_cache_only(regmap, true); +- regcache_mark_dirty(regmap); ++ if (wcd->regmap) { ++ regcache_cache_only(wcd->regmap, true); ++ regcache_mark_dirty(wcd->regmap); + } ++ + return 0; + } + + static int __maybe_unused wcd938x_sdw_runtime_resume(struct device *dev) + { +- struct regmap *regmap = dev_get_regmap(dev, NULL); ++ struct wcd938x_sdw_priv *wcd = dev_get_drvdata(dev); + +- if (regmap) { +- regcache_cache_only(regmap, false); +- regcache_sync(regmap); ++ if (wcd->regmap) { ++ regcache_cache_only(wcd->regmap, false); ++ regcache_sync(wcd->regmap); + } + + pm_runtime_mark_last_busy(dev); +diff --git a/sound/soc/codecs/wcd938x.c b/sound/soc/codecs/wcd938x.c +index 1fa58e2bff3d0..16e2e1c186846 100644 +--- a/sound/soc/codecs/wcd938x.c ++++ b/sound/soc/codecs/wcd938x.c +@@ -271,1001 +271,6 @@ static struct wcd_mbhc_field wcd_mbhc_fields[WCD_MBHC_REG_FUNC_MAX] = { + WCD_MBHC_FIELD(WCD_MBHC_ELECT_ISRC_EN, WCD938X_ANA_MBHC_ZDET, 0x02), + }; + +-static const struct reg_default wcd938x_defaults[] = { +- {WCD938X_ANA_PAGE_REGISTER, 0x00}, +- {WCD938X_ANA_BIAS, 0x00}, +- {WCD938X_ANA_RX_SUPPLIES, 0x00}, +- {WCD938X_ANA_HPH, 0x0C}, +- {WCD938X_ANA_EAR, 0x00}, +- {WCD938X_ANA_EAR_COMPANDER_CTL, 0x02}, +- {WCD938X_ANA_TX_CH1, 0x20}, +- {WCD938X_ANA_TX_CH2, 0x00}, +- {WCD938X_ANA_TX_CH3, 0x20}, +- {WCD938X_ANA_TX_CH4, 0x00}, +- {WCD938X_ANA_MICB1_MICB2_DSP_EN_LOGIC, 0x00}, +- {WCD938X_ANA_MICB3_DSP_EN_LOGIC, 0x00}, +- {WCD938X_ANA_MBHC_MECH, 0x39}, +- {WCD938X_ANA_MBHC_ELECT, 0x08}, +- {WCD938X_ANA_MBHC_ZDET, 0x00}, +- {WCD938X_ANA_MBHC_RESULT_1, 0x00}, +- {WCD938X_ANA_MBHC_RESULT_2, 0x00}, +- {WCD938X_ANA_MBHC_RESULT_3, 0x00}, +- {WCD938X_ANA_MBHC_BTN0, 0x00}, +- {WCD938X_ANA_MBHC_BTN1, 0x10}, +- {WCD938X_ANA_MBHC_BTN2, 0x20}, +- {WCD938X_ANA_MBHC_BTN3, 0x30}, +- {WCD938X_ANA_MBHC_BTN4, 0x40}, +- {WCD938X_ANA_MBHC_BTN5, 0x50}, +- {WCD938X_ANA_MBHC_BTN6, 0x60}, +- {WCD938X_ANA_MBHC_BTN7, 0x70}, +- {WCD938X_ANA_MICB1, 0x10}, +- {WCD938X_ANA_MICB2, 0x10}, +- {WCD938X_ANA_MICB2_RAMP, 0x00}, +- {WCD938X_ANA_MICB3, 0x10}, +- {WCD938X_ANA_MICB4, 0x10}, +- {WCD938X_BIAS_CTL, 0x2A}, +- {WCD938X_BIAS_VBG_FINE_ADJ, 0x55}, +- {WCD938X_LDOL_VDDCX_ADJUST, 0x01}, +- {WCD938X_LDOL_DISABLE_LDOL, 0x00}, +- {WCD938X_MBHC_CTL_CLK, 0x00}, +- {WCD938X_MBHC_CTL_ANA, 0x00}, +- {WCD938X_MBHC_CTL_SPARE_1, 0x00}, +- {WCD938X_MBHC_CTL_SPARE_2, 0x00}, +- {WCD938X_MBHC_CTL_BCS, 0x00}, +- {WCD938X_MBHC_MOISTURE_DET_FSM_STATUS, 0x00}, +- {WCD938X_MBHC_TEST_CTL, 0x00}, +- {WCD938X_LDOH_MODE, 0x2B}, +- {WCD938X_LDOH_BIAS, 0x68}, +- {WCD938X_LDOH_STB_LOADS, 0x00}, +- {WCD938X_LDOH_SLOWRAMP, 0x50}, +- {WCD938X_MICB1_TEST_CTL_1, 0x1A}, +- {WCD938X_MICB1_TEST_CTL_2, 0x00}, +- {WCD938X_MICB1_TEST_CTL_3, 0xA4}, +- {WCD938X_MICB2_TEST_CTL_1, 0x1A}, +- {WCD938X_MICB2_TEST_CTL_2, 0x00}, +- {WCD938X_MICB2_TEST_CTL_3, 0x24}, +- {WCD938X_MICB3_TEST_CTL_1, 0x1A}, +- {WCD938X_MICB3_TEST_CTL_2, 0x00}, +- {WCD938X_MICB3_TEST_CTL_3, 0xA4}, +- {WCD938X_MICB4_TEST_CTL_1, 0x1A}, +- {WCD938X_MICB4_TEST_CTL_2, 0x00}, +- {WCD938X_MICB4_TEST_CTL_3, 0xA4}, +- {WCD938X_TX_COM_ADC_VCM, 0x39}, +- {WCD938X_TX_COM_BIAS_ATEST, 0xE0}, +- {WCD938X_TX_COM_SPARE1, 0x00}, +- {WCD938X_TX_COM_SPARE2, 0x00}, +- {WCD938X_TX_COM_TXFE_DIV_CTL, 0x22}, +- {WCD938X_TX_COM_TXFE_DIV_START, 0x00}, +- {WCD938X_TX_COM_SPARE3, 0x00}, +- {WCD938X_TX_COM_SPARE4, 0x00}, +- {WCD938X_TX_1_2_TEST_EN, 0xCC}, +- {WCD938X_TX_1_2_ADC_IB, 0xE9}, +- {WCD938X_TX_1_2_ATEST_REFCTL, 0x0A}, +- {WCD938X_TX_1_2_TEST_CTL, 0x38}, +- {WCD938X_TX_1_2_TEST_BLK_EN1, 0xFF}, +- {WCD938X_TX_1_2_TXFE1_CLKDIV, 0x00}, +- {WCD938X_TX_1_2_SAR2_ERR, 0x00}, +- {WCD938X_TX_1_2_SAR1_ERR, 0x00}, +- {WCD938X_TX_3_4_TEST_EN, 0xCC}, +- {WCD938X_TX_3_4_ADC_IB, 0xE9}, +- {WCD938X_TX_3_4_ATEST_REFCTL, 0x0A}, +- {WCD938X_TX_3_4_TEST_CTL, 0x38}, +- {WCD938X_TX_3_4_TEST_BLK_EN3, 0xFF}, +- {WCD938X_TX_3_4_TXFE3_CLKDIV, 0x00}, +- {WCD938X_TX_3_4_SAR4_ERR, 0x00}, +- {WCD938X_TX_3_4_SAR3_ERR, 0x00}, +- {WCD938X_TX_3_4_TEST_BLK_EN2, 0xFB}, +- {WCD938X_TX_3_4_TXFE2_CLKDIV, 0x00}, +- {WCD938X_TX_3_4_SPARE1, 0x00}, +- {WCD938X_TX_3_4_TEST_BLK_EN4, 0xFB}, +- {WCD938X_TX_3_4_TXFE4_CLKDIV, 0x00}, +- {WCD938X_TX_3_4_SPARE2, 0x00}, +- {WCD938X_CLASSH_MODE_1, 0x40}, +- {WCD938X_CLASSH_MODE_2, 0x3A}, +- {WCD938X_CLASSH_MODE_3, 0x00}, +- {WCD938X_CLASSH_CTRL_VCL_1, 0x70}, +- {WCD938X_CLASSH_CTRL_VCL_2, 0x82}, +- {WCD938X_CLASSH_CTRL_CCL_1, 0x31}, +- {WCD938X_CLASSH_CTRL_CCL_2, 0x80}, +- {WCD938X_CLASSH_CTRL_CCL_3, 0x80}, +- {WCD938X_CLASSH_CTRL_CCL_4, 0x51}, +- {WCD938X_CLASSH_CTRL_CCL_5, 0x00}, +- {WCD938X_CLASSH_BUCK_TMUX_A_D, 0x00}, +- {WCD938X_CLASSH_BUCK_SW_DRV_CNTL, 0x77}, +- {WCD938X_CLASSH_SPARE, 0x00}, +- {WCD938X_FLYBACK_EN, 0x4E}, +- {WCD938X_FLYBACK_VNEG_CTRL_1, 0x0B}, +- {WCD938X_FLYBACK_VNEG_CTRL_2, 0x45}, +- {WCD938X_FLYBACK_VNEG_CTRL_3, 0x74}, +- {WCD938X_FLYBACK_VNEG_CTRL_4, 0x7F}, +- {WCD938X_FLYBACK_VNEG_CTRL_5, 0x83}, +- {WCD938X_FLYBACK_VNEG_CTRL_6, 0x98}, +- {WCD938X_FLYBACK_VNEG_CTRL_7, 0xA9}, +- {WCD938X_FLYBACK_VNEG_CTRL_8, 0x68}, +- {WCD938X_FLYBACK_VNEG_CTRL_9, 0x64}, +- {WCD938X_FLYBACK_VNEGDAC_CTRL_1, 0xED}, +- {WCD938X_FLYBACK_VNEGDAC_CTRL_2, 0xF0}, +- {WCD938X_FLYBACK_VNEGDAC_CTRL_3, 0xA6}, +- {WCD938X_FLYBACK_CTRL_1, 0x65}, +- {WCD938X_FLYBACK_TEST_CTL, 0x00}, +- {WCD938X_RX_AUX_SW_CTL, 0x00}, +- {WCD938X_RX_PA_AUX_IN_CONN, 0x01}, +- {WCD938X_RX_TIMER_DIV, 0x32}, +- {WCD938X_RX_OCP_CTL, 0x1F}, +- {WCD938X_RX_OCP_COUNT, 0x77}, +- {WCD938X_RX_BIAS_EAR_DAC, 0xA0}, +- {WCD938X_RX_BIAS_EAR_AMP, 0xAA}, +- {WCD938X_RX_BIAS_HPH_LDO, 0xA9}, +- {WCD938X_RX_BIAS_HPH_PA, 0xAA}, +- {WCD938X_RX_BIAS_HPH_RDACBUFF_CNP2, 0x8A}, +- {WCD938X_RX_BIAS_HPH_RDAC_LDO, 0x88}, +- {WCD938X_RX_BIAS_HPH_CNP1, 0x82}, +- {WCD938X_RX_BIAS_HPH_LOWPOWER, 0x82}, +- {WCD938X_RX_BIAS_AUX_DAC, 0xA0}, +- {WCD938X_RX_BIAS_AUX_AMP, 0xAA}, +- {WCD938X_RX_BIAS_VNEGDAC_BLEEDER, 0x50}, +- {WCD938X_RX_BIAS_MISC, 0x00}, +- {WCD938X_RX_BIAS_BUCK_RST, 0x08}, +- {WCD938X_RX_BIAS_BUCK_VREF_ERRAMP, 0x44}, +- {WCD938X_RX_BIAS_FLYB_ERRAMP, 0x40}, +- {WCD938X_RX_BIAS_FLYB_BUFF, 0xAA}, +- {WCD938X_RX_BIAS_FLYB_MID_RST, 0x14}, +- {WCD938X_HPH_L_STATUS, 0x04}, +- {WCD938X_HPH_R_STATUS, 0x04}, +- {WCD938X_HPH_CNP_EN, 0x80}, +- {WCD938X_HPH_CNP_WG_CTL, 0x9A}, +- {WCD938X_HPH_CNP_WG_TIME, 0x14}, +- {WCD938X_HPH_OCP_CTL, 0x28}, +- {WCD938X_HPH_AUTO_CHOP, 0x16}, +- {WCD938X_HPH_CHOP_CTL, 0x83}, +- {WCD938X_HPH_PA_CTL1, 0x46}, +- {WCD938X_HPH_PA_CTL2, 0x50}, +- {WCD938X_HPH_L_EN, 0x80}, +- {WCD938X_HPH_L_TEST, 0xE0}, +- {WCD938X_HPH_L_ATEST, 0x50}, +- {WCD938X_HPH_R_EN, 0x80}, +- {WCD938X_HPH_R_TEST, 0xE0}, +- {WCD938X_HPH_R_ATEST, 0x54}, +- {WCD938X_HPH_RDAC_CLK_CTL1, 0x99}, +- {WCD938X_HPH_RDAC_CLK_CTL2, 0x9B}, +- {WCD938X_HPH_RDAC_LDO_CTL, 0x33}, +- {WCD938X_HPH_RDAC_CHOP_CLK_LP_CTL, 0x00}, +- {WCD938X_HPH_REFBUFF_UHQA_CTL, 0x68}, +- {WCD938X_HPH_REFBUFF_LP_CTL, 0x0E}, +- {WCD938X_HPH_L_DAC_CTL, 0x20}, +- {WCD938X_HPH_R_DAC_CTL, 0x20}, +- {WCD938X_HPH_SURGE_HPHLR_SURGE_COMP_SEL, 0x55}, +- {WCD938X_HPH_SURGE_HPHLR_SURGE_EN, 0x19}, +- {WCD938X_HPH_SURGE_HPHLR_SURGE_MISC1, 0xA0}, +- {WCD938X_HPH_SURGE_HPHLR_SURGE_STATUS, 0x00}, +- {WCD938X_EAR_EAR_EN_REG, 0x22}, +- {WCD938X_EAR_EAR_PA_CON, 0x44}, +- {WCD938X_EAR_EAR_SP_CON, 0xDB}, +- {WCD938X_EAR_EAR_DAC_CON, 0x80}, +- {WCD938X_EAR_EAR_CNP_FSM_CON, 0xB2}, +- {WCD938X_EAR_TEST_CTL, 0x00}, +- {WCD938X_EAR_STATUS_REG_1, 0x00}, +- {WCD938X_EAR_STATUS_REG_2, 0x08}, +- {WCD938X_ANA_NEW_PAGE_REGISTER, 0x00}, +- {WCD938X_HPH_NEW_ANA_HPH2, 0x00}, +- {WCD938X_HPH_NEW_ANA_HPH3, 0x00}, +- {WCD938X_SLEEP_CTL, 0x16}, +- {WCD938X_SLEEP_WATCHDOG_CTL, 0x00}, +- {WCD938X_MBHC_NEW_ELECT_REM_CLAMP_CTL, 0x00}, +- {WCD938X_MBHC_NEW_CTL_1, 0x02}, +- {WCD938X_MBHC_NEW_CTL_2, 0x05}, +- {WCD938X_MBHC_NEW_PLUG_DETECT_CTL, 0xE9}, +- {WCD938X_MBHC_NEW_ZDET_ANA_CTL, 0x0F}, +- {WCD938X_MBHC_NEW_ZDET_RAMP_CTL, 0x00}, +- {WCD938X_MBHC_NEW_FSM_STATUS, 0x00}, +- {WCD938X_MBHC_NEW_ADC_RESULT, 0x00}, +- {WCD938X_TX_NEW_AMIC_MUX_CFG, 0x00}, +- {WCD938X_AUX_AUXPA, 0x00}, +- {WCD938X_LDORXTX_MODE, 0x0C}, +- {WCD938X_LDORXTX_CONFIG, 0x10}, +- {WCD938X_DIE_CRACK_DIE_CRK_DET_EN, 0x00}, +- {WCD938X_DIE_CRACK_DIE_CRK_DET_OUT, 0x00}, +- {WCD938X_HPH_NEW_INT_RDAC_GAIN_CTL, 0x40}, +- {WCD938X_HPH_NEW_INT_RDAC_HD2_CTL_L, 0x81}, +- {WCD938X_HPH_NEW_INT_RDAC_VREF_CTL, 0x10}, +- {WCD938X_HPH_NEW_INT_RDAC_OVERRIDE_CTL, 0x00}, +- {WCD938X_HPH_NEW_INT_RDAC_HD2_CTL_R, 0x81}, +- {WCD938X_HPH_NEW_INT_PA_MISC1, 0x22}, +- {WCD938X_HPH_NEW_INT_PA_MISC2, 0x00}, +- {WCD938X_HPH_NEW_INT_PA_RDAC_MISC, 0x00}, +- {WCD938X_HPH_NEW_INT_HPH_TIMER1, 0xFE}, +- {WCD938X_HPH_NEW_INT_HPH_TIMER2, 0x02}, +- {WCD938X_HPH_NEW_INT_HPH_TIMER3, 0x4E}, +- {WCD938X_HPH_NEW_INT_HPH_TIMER4, 0x54}, +- {WCD938X_HPH_NEW_INT_PA_RDAC_MISC2, 0x00}, +- {WCD938X_HPH_NEW_INT_PA_RDAC_MISC3, 0x00}, +- {WCD938X_HPH_NEW_INT_RDAC_HD2_CTL_L_NEW, 0x90}, +- {WCD938X_HPH_NEW_INT_RDAC_HD2_CTL_R_NEW, 0x90}, +- {WCD938X_RX_NEW_INT_HPH_RDAC_BIAS_LOHIFI, 0x62}, +- {WCD938X_RX_NEW_INT_HPH_RDAC_BIAS_ULP, 0x01}, +- {WCD938X_RX_NEW_INT_HPH_RDAC_LDO_LP, 0x11}, +- {WCD938X_MBHC_NEW_INT_MOISTURE_DET_DC_CTRL, 0x57}, +- {WCD938X_MBHC_NEW_INT_MOISTURE_DET_POLLING_CTRL, 0x01}, +- {WCD938X_MBHC_NEW_INT_MECH_DET_CURRENT, 0x00}, +- {WCD938X_MBHC_NEW_INT_SPARE_2, 0x00}, +- {WCD938X_EAR_INT_NEW_EAR_CHOPPER_CON, 0xA8}, +- {WCD938X_EAR_INT_NEW_CNP_VCM_CON1, 0x42}, +- {WCD938X_EAR_INT_NEW_CNP_VCM_CON2, 0x22}, +- {WCD938X_EAR_INT_NEW_EAR_DYNAMIC_BIAS, 0x00}, +- {WCD938X_AUX_INT_EN_REG, 0x00}, +- {WCD938X_AUX_INT_PA_CTRL, 0x06}, +- {WCD938X_AUX_INT_SP_CTRL, 0xD2}, +- {WCD938X_AUX_INT_DAC_CTRL, 0x80}, +- {WCD938X_AUX_INT_CLK_CTRL, 0x50}, +- {WCD938X_AUX_INT_TEST_CTRL, 0x00}, +- {WCD938X_AUX_INT_STATUS_REG, 0x00}, +- {WCD938X_AUX_INT_MISC, 0x00}, +- {WCD938X_LDORXTX_INT_BIAS, 0x6E}, +- {WCD938X_LDORXTX_INT_STB_LOADS_DTEST, 0x50}, +- {WCD938X_LDORXTX_INT_TEST0, 0x1C}, +- {WCD938X_LDORXTX_INT_STARTUP_TIMER, 0xFF}, +- {WCD938X_LDORXTX_INT_TEST1, 0x1F}, +- {WCD938X_LDORXTX_INT_STATUS, 0x00}, +- {WCD938X_SLEEP_INT_WATCHDOG_CTL_1, 0x0A}, +- {WCD938X_SLEEP_INT_WATCHDOG_CTL_2, 0x0A}, +- {WCD938X_DIE_CRACK_INT_DIE_CRK_DET_INT1, 0x02}, +- {WCD938X_DIE_CRACK_INT_DIE_CRK_DET_INT2, 0x60}, +- {WCD938X_TX_COM_NEW_INT_TXFE_DIVSTOP_L2, 0xFF}, +- {WCD938X_TX_COM_NEW_INT_TXFE_DIVSTOP_L1, 0x7F}, +- {WCD938X_TX_COM_NEW_INT_TXFE_DIVSTOP_L0, 0x3F}, +- {WCD938X_TX_COM_NEW_INT_TXFE_DIVSTOP_ULP1P2M, 0x1F}, +- {WCD938X_TX_COM_NEW_INT_TXFE_DIVSTOP_ULP0P6M, 0x0F}, +- {WCD938X_TX_COM_NEW_INT_TXFE_ICTRL_STG1_L2L1, 0xD7}, +- {WCD938X_TX_COM_NEW_INT_TXFE_ICTRL_STG1_L0, 0xC8}, +- {WCD938X_TX_COM_NEW_INT_TXFE_ICTRL_STG1_ULP, 0xC6}, +- {WCD938X_TX_COM_NEW_INT_TXFE_ICTRL_STG2MAIN_L2L1, 0xD5}, +- {WCD938X_TX_COM_NEW_INT_TXFE_ICTRL_STG2MAIN_L0, 0xCA}, +- {WCD938X_TX_COM_NEW_INT_TXFE_ICTRL_STG2MAIN_ULP, 0x05}, +- {WCD938X_TX_COM_NEW_INT_TXFE_ICTRL_STG2CASC_L2L1L0, 0xA5}, +- {WCD938X_TX_COM_NEW_INT_TXFE_ICTRL_STG2CASC_ULP, 0x13}, +- {WCD938X_TX_COM_NEW_INT_TXADC_SCBIAS_L2L1, 0x88}, +- {WCD938X_TX_COM_NEW_INT_TXADC_SCBIAS_L0ULP, 0x42}, +- {WCD938X_TX_COM_NEW_INT_TXADC_INT_L2, 0xFF}, +- {WCD938X_TX_COM_NEW_INT_TXADC_INT_L1, 0x64}, +- {WCD938X_TX_COM_NEW_INT_TXADC_INT_L0, 0x64}, +- {WCD938X_TX_COM_NEW_INT_TXADC_INT_ULP, 0x77}, +- {WCD938X_DIGITAL_PAGE_REGISTER, 0x00}, +- {WCD938X_DIGITAL_CHIP_ID0, 0x00}, +- {WCD938X_DIGITAL_CHIP_ID1, 0x00}, +- {WCD938X_DIGITAL_CHIP_ID2, 0x0D}, +- {WCD938X_DIGITAL_CHIP_ID3, 0x01}, +- {WCD938X_DIGITAL_SWR_TX_CLK_RATE, 0x00}, +- {WCD938X_DIGITAL_CDC_RST_CTL, 0x03}, +- {WCD938X_DIGITAL_TOP_CLK_CFG, 0x00}, +- {WCD938X_DIGITAL_CDC_ANA_CLK_CTL, 0x00}, +- {WCD938X_DIGITAL_CDC_DIG_CLK_CTL, 0xF0}, +- {WCD938X_DIGITAL_SWR_RST_EN, 0x00}, +- {WCD938X_DIGITAL_CDC_PATH_MODE, 0x55}, +- {WCD938X_DIGITAL_CDC_RX_RST, 0x00}, +- {WCD938X_DIGITAL_CDC_RX0_CTL, 0xFC}, +- {WCD938X_DIGITAL_CDC_RX1_CTL, 0xFC}, +- {WCD938X_DIGITAL_CDC_RX2_CTL, 0xFC}, +- {WCD938X_DIGITAL_CDC_TX_ANA_MODE_0_1, 0x00}, +- {WCD938X_DIGITAL_CDC_TX_ANA_MODE_2_3, 0x00}, +- {WCD938X_DIGITAL_CDC_COMP_CTL_0, 0x00}, +- {WCD938X_DIGITAL_CDC_ANA_TX_CLK_CTL, 0x1E}, +- {WCD938X_DIGITAL_CDC_HPH_DSM_A1_0, 0x00}, +- {WCD938X_DIGITAL_CDC_HPH_DSM_A1_1, 0x01}, +- {WCD938X_DIGITAL_CDC_HPH_DSM_A2_0, 0x63}, +- {WCD938X_DIGITAL_CDC_HPH_DSM_A2_1, 0x04}, +- {WCD938X_DIGITAL_CDC_HPH_DSM_A3_0, 0xAC}, +- {WCD938X_DIGITAL_CDC_HPH_DSM_A3_1, 0x04}, +- {WCD938X_DIGITAL_CDC_HPH_DSM_A4_0, 0x1A}, +- {WCD938X_DIGITAL_CDC_HPH_DSM_A4_1, 0x03}, +- {WCD938X_DIGITAL_CDC_HPH_DSM_A5_0, 0xBC}, +- {WCD938X_DIGITAL_CDC_HPH_DSM_A5_1, 0x02}, +- {WCD938X_DIGITAL_CDC_HPH_DSM_A6_0, 0xC7}, +- {WCD938X_DIGITAL_CDC_HPH_DSM_A7_0, 0xF8}, +- {WCD938X_DIGITAL_CDC_HPH_DSM_C_0, 0x47}, +- {WCD938X_DIGITAL_CDC_HPH_DSM_C_1, 0x43}, +- {WCD938X_DIGITAL_CDC_HPH_DSM_C_2, 0xB1}, +- {WCD938X_DIGITAL_CDC_HPH_DSM_C_3, 0x17}, +- {WCD938X_DIGITAL_CDC_HPH_DSM_R1, 0x4D}, +- {WCD938X_DIGITAL_CDC_HPH_DSM_R2, 0x29}, +- {WCD938X_DIGITAL_CDC_HPH_DSM_R3, 0x34}, +- {WCD938X_DIGITAL_CDC_HPH_DSM_R4, 0x59}, +- {WCD938X_DIGITAL_CDC_HPH_DSM_R5, 0x66}, +- {WCD938X_DIGITAL_CDC_HPH_DSM_R6, 0x87}, +- {WCD938X_DIGITAL_CDC_HPH_DSM_R7, 0x64}, +- {WCD938X_DIGITAL_CDC_AUX_DSM_A1_0, 0x00}, +- {WCD938X_DIGITAL_CDC_AUX_DSM_A1_1, 0x01}, +- {WCD938X_DIGITAL_CDC_AUX_DSM_A2_0, 0x96}, +- {WCD938X_DIGITAL_CDC_AUX_DSM_A2_1, 0x09}, +- {WCD938X_DIGITAL_CDC_AUX_DSM_A3_0, 0xAB}, +- {WCD938X_DIGITAL_CDC_AUX_DSM_A3_1, 0x05}, +- {WCD938X_DIGITAL_CDC_AUX_DSM_A4_0, 0x1C}, +- {WCD938X_DIGITAL_CDC_AUX_DSM_A4_1, 0x02}, +- {WCD938X_DIGITAL_CDC_AUX_DSM_A5_0, 0x17}, +- {WCD938X_DIGITAL_CDC_AUX_DSM_A5_1, 0x02}, +- {WCD938X_DIGITAL_CDC_AUX_DSM_A6_0, 0xAA}, +- {WCD938X_DIGITAL_CDC_AUX_DSM_A7_0, 0xE3}, +- {WCD938X_DIGITAL_CDC_AUX_DSM_C_0, 0x69}, +- {WCD938X_DIGITAL_CDC_AUX_DSM_C_1, 0x54}, +- {WCD938X_DIGITAL_CDC_AUX_DSM_C_2, 0x02}, +- {WCD938X_DIGITAL_CDC_AUX_DSM_C_3, 0x15}, +- {WCD938X_DIGITAL_CDC_AUX_DSM_R1, 0xA4}, +- {WCD938X_DIGITAL_CDC_AUX_DSM_R2, 0xB5}, +- {WCD938X_DIGITAL_CDC_AUX_DSM_R3, 0x86}, +- {WCD938X_DIGITAL_CDC_AUX_DSM_R4, 0x85}, +- {WCD938X_DIGITAL_CDC_AUX_DSM_R5, 0xAA}, +- {WCD938X_DIGITAL_CDC_AUX_DSM_R6, 0xE2}, +- {WCD938X_DIGITAL_CDC_AUX_DSM_R7, 0x62}, +- {WCD938X_DIGITAL_CDC_HPH_GAIN_RX_0, 0x55}, +- {WCD938X_DIGITAL_CDC_HPH_GAIN_RX_1, 0xA9}, +- {WCD938X_DIGITAL_CDC_HPH_GAIN_DSD_0, 0x3D}, +- {WCD938X_DIGITAL_CDC_HPH_GAIN_DSD_1, 0x2E}, +- {WCD938X_DIGITAL_CDC_HPH_GAIN_DSD_2, 0x01}, +- {WCD938X_DIGITAL_CDC_AUX_GAIN_DSD_0, 0x00}, +- {WCD938X_DIGITAL_CDC_AUX_GAIN_DSD_1, 0xFC}, +- {WCD938X_DIGITAL_CDC_AUX_GAIN_DSD_2, 0x01}, +- {WCD938X_DIGITAL_CDC_HPH_GAIN_CTL, 0x00}, +- {WCD938X_DIGITAL_CDC_AUX_GAIN_CTL, 0x00}, +- {WCD938X_DIGITAL_CDC_EAR_PATH_CTL, 0x00}, +- {WCD938X_DIGITAL_CDC_SWR_CLH, 0x00}, +- {WCD938X_DIGITAL_SWR_CLH_BYP, 0x00}, +- {WCD938X_DIGITAL_CDC_TX0_CTL, 0x68}, +- {WCD938X_DIGITAL_CDC_TX1_CTL, 0x68}, +- {WCD938X_DIGITAL_CDC_TX2_CTL, 0x68}, +- {WCD938X_DIGITAL_CDC_TX_RST, 0x00}, +- {WCD938X_DIGITAL_CDC_REQ_CTL, 0x01}, +- {WCD938X_DIGITAL_CDC_RST, 0x00}, +- {WCD938X_DIGITAL_CDC_AMIC_CTL, 0x0F}, +- {WCD938X_DIGITAL_CDC_DMIC_CTL, 0x04}, +- {WCD938X_DIGITAL_CDC_DMIC1_CTL, 0x01}, +- {WCD938X_DIGITAL_CDC_DMIC2_CTL, 0x01}, +- {WCD938X_DIGITAL_CDC_DMIC3_CTL, 0x01}, +- {WCD938X_DIGITAL_CDC_DMIC4_CTL, 0x01}, +- {WCD938X_DIGITAL_EFUSE_PRG_CTL, 0x00}, +- {WCD938X_DIGITAL_EFUSE_CTL, 0x2B}, +- {WCD938X_DIGITAL_CDC_DMIC_RATE_1_2, 0x11}, +- {WCD938X_DIGITAL_CDC_DMIC_RATE_3_4, 0x11}, +- {WCD938X_DIGITAL_PDM_WD_CTL0, 0x00}, +- {WCD938X_DIGITAL_PDM_WD_CTL1, 0x00}, +- {WCD938X_DIGITAL_PDM_WD_CTL2, 0x00}, +- {WCD938X_DIGITAL_INTR_MODE, 0x00}, +- {WCD938X_DIGITAL_INTR_MASK_0, 0xFF}, +- {WCD938X_DIGITAL_INTR_MASK_1, 0xFF}, +- {WCD938X_DIGITAL_INTR_MASK_2, 0x3F}, +- {WCD938X_DIGITAL_INTR_STATUS_0, 0x00}, +- {WCD938X_DIGITAL_INTR_STATUS_1, 0x00}, +- {WCD938X_DIGITAL_INTR_STATUS_2, 0x00}, +- {WCD938X_DIGITAL_INTR_CLEAR_0, 0x00}, +- {WCD938X_DIGITAL_INTR_CLEAR_1, 0x00}, +- {WCD938X_DIGITAL_INTR_CLEAR_2, 0x00}, +- {WCD938X_DIGITAL_INTR_LEVEL_0, 0x00}, +- {WCD938X_DIGITAL_INTR_LEVEL_1, 0x00}, +- {WCD938X_DIGITAL_INTR_LEVEL_2, 0x00}, +- {WCD938X_DIGITAL_INTR_SET_0, 0x00}, +- {WCD938X_DIGITAL_INTR_SET_1, 0x00}, +- {WCD938X_DIGITAL_INTR_SET_2, 0x00}, +- {WCD938X_DIGITAL_INTR_TEST_0, 0x00}, +- {WCD938X_DIGITAL_INTR_TEST_1, 0x00}, +- {WCD938X_DIGITAL_INTR_TEST_2, 0x00}, +- {WCD938X_DIGITAL_TX_MODE_DBG_EN, 0x00}, +- {WCD938X_DIGITAL_TX_MODE_DBG_0_1, 0x00}, +- {WCD938X_DIGITAL_TX_MODE_DBG_2_3, 0x00}, +- {WCD938X_DIGITAL_LB_IN_SEL_CTL, 0x00}, +- {WCD938X_DIGITAL_LOOP_BACK_MODE, 0x00}, +- {WCD938X_DIGITAL_SWR_DAC_TEST, 0x00}, +- {WCD938X_DIGITAL_SWR_HM_TEST_RX_0, 0x40}, +- {WCD938X_DIGITAL_SWR_HM_TEST_TX_0, 0x40}, +- {WCD938X_DIGITAL_SWR_HM_TEST_RX_1, 0x00}, +- {WCD938X_DIGITAL_SWR_HM_TEST_TX_1, 0x00}, +- {WCD938X_DIGITAL_SWR_HM_TEST_TX_2, 0x00}, +- {WCD938X_DIGITAL_SWR_HM_TEST_0, 0x00}, +- {WCD938X_DIGITAL_SWR_HM_TEST_1, 0x00}, +- {WCD938X_DIGITAL_PAD_CTL_SWR_0, 0x8F}, +- {WCD938X_DIGITAL_PAD_CTL_SWR_1, 0x06}, +- {WCD938X_DIGITAL_I2C_CTL, 0x00}, +- {WCD938X_DIGITAL_CDC_TX_TANGGU_SW_MODE, 0x00}, +- {WCD938X_DIGITAL_EFUSE_TEST_CTL_0, 0x00}, +- {WCD938X_DIGITAL_EFUSE_TEST_CTL_1, 0x00}, +- {WCD938X_DIGITAL_EFUSE_T_DATA_0, 0x00}, +- {WCD938X_DIGITAL_EFUSE_T_DATA_1, 0x00}, +- {WCD938X_DIGITAL_PAD_CTL_PDM_RX0, 0xF1}, +- {WCD938X_DIGITAL_PAD_CTL_PDM_RX1, 0xF1}, +- {WCD938X_DIGITAL_PAD_CTL_PDM_TX0, 0xF1}, +- {WCD938X_DIGITAL_PAD_CTL_PDM_TX1, 0xF1}, +- {WCD938X_DIGITAL_PAD_CTL_PDM_TX2, 0xF1}, +- {WCD938X_DIGITAL_PAD_INP_DIS_0, 0x00}, +- {WCD938X_DIGITAL_PAD_INP_DIS_1, 0x00}, +- {WCD938X_DIGITAL_DRIVE_STRENGTH_0, 0x00}, +- {WCD938X_DIGITAL_DRIVE_STRENGTH_1, 0x00}, +- {WCD938X_DIGITAL_DRIVE_STRENGTH_2, 0x00}, +- {WCD938X_DIGITAL_RX_DATA_EDGE_CTL, 0x1F}, +- {WCD938X_DIGITAL_TX_DATA_EDGE_CTL, 0x80}, +- {WCD938X_DIGITAL_GPIO_MODE, 0x00}, +- {WCD938X_DIGITAL_PIN_CTL_OE, 0x00}, +- {WCD938X_DIGITAL_PIN_CTL_DATA_0, 0x00}, +- {WCD938X_DIGITAL_PIN_CTL_DATA_1, 0x00}, +- {WCD938X_DIGITAL_PIN_STATUS_0, 0x00}, +- {WCD938X_DIGITAL_PIN_STATUS_1, 0x00}, +- {WCD938X_DIGITAL_DIG_DEBUG_CTL, 0x00}, +- {WCD938X_DIGITAL_DIG_DEBUG_EN, 0x00}, +- {WCD938X_DIGITAL_ANA_CSR_DBG_ADD, 0x00}, +- {WCD938X_DIGITAL_ANA_CSR_DBG_CTL, 0x48}, +- {WCD938X_DIGITAL_SSP_DBG, 0x00}, +- {WCD938X_DIGITAL_MODE_STATUS_0, 0x00}, +- {WCD938X_DIGITAL_MODE_STATUS_1, 0x00}, +- {WCD938X_DIGITAL_SPARE_0, 0x00}, +- {WCD938X_DIGITAL_SPARE_1, 0x00}, +- {WCD938X_DIGITAL_SPARE_2, 0x00}, +- {WCD938X_DIGITAL_EFUSE_REG_0, 0x00}, +- {WCD938X_DIGITAL_EFUSE_REG_1, 0xFF}, +- {WCD938X_DIGITAL_EFUSE_REG_2, 0xFF}, +- {WCD938X_DIGITAL_EFUSE_REG_3, 0xFF}, +- {WCD938X_DIGITAL_EFUSE_REG_4, 0xFF}, +- {WCD938X_DIGITAL_EFUSE_REG_5, 0xFF}, +- {WCD938X_DIGITAL_EFUSE_REG_6, 0xFF}, +- {WCD938X_DIGITAL_EFUSE_REG_7, 0xFF}, +- {WCD938X_DIGITAL_EFUSE_REG_8, 0xFF}, +- {WCD938X_DIGITAL_EFUSE_REG_9, 0xFF}, +- {WCD938X_DIGITAL_EFUSE_REG_10, 0xFF}, +- {WCD938X_DIGITAL_EFUSE_REG_11, 0xFF}, +- {WCD938X_DIGITAL_EFUSE_REG_12, 0xFF}, +- {WCD938X_DIGITAL_EFUSE_REG_13, 0xFF}, +- {WCD938X_DIGITAL_EFUSE_REG_14, 0xFF}, +- {WCD938X_DIGITAL_EFUSE_REG_15, 0xFF}, +- {WCD938X_DIGITAL_EFUSE_REG_16, 0xFF}, +- {WCD938X_DIGITAL_EFUSE_REG_17, 0xFF}, +- {WCD938X_DIGITAL_EFUSE_REG_18, 0xFF}, +- {WCD938X_DIGITAL_EFUSE_REG_19, 0xFF}, +- {WCD938X_DIGITAL_EFUSE_REG_20, 0x0E}, +- {WCD938X_DIGITAL_EFUSE_REG_21, 0x00}, +- {WCD938X_DIGITAL_EFUSE_REG_22, 0x00}, +- {WCD938X_DIGITAL_EFUSE_REG_23, 0xF8}, +- {WCD938X_DIGITAL_EFUSE_REG_24, 0x16}, +- {WCD938X_DIGITAL_EFUSE_REG_25, 0x00}, +- {WCD938X_DIGITAL_EFUSE_REG_26, 0x00}, +- {WCD938X_DIGITAL_EFUSE_REG_27, 0x00}, +- {WCD938X_DIGITAL_EFUSE_REG_28, 0x00}, +- {WCD938X_DIGITAL_EFUSE_REG_29, 0x00}, +- {WCD938X_DIGITAL_EFUSE_REG_30, 0x00}, +- {WCD938X_DIGITAL_EFUSE_REG_31, 0x00}, +- {WCD938X_DIGITAL_TX_REQ_FB_CTL_0, 0x88}, +- {WCD938X_DIGITAL_TX_REQ_FB_CTL_1, 0x88}, +- {WCD938X_DIGITAL_TX_REQ_FB_CTL_2, 0x88}, +- {WCD938X_DIGITAL_TX_REQ_FB_CTL_3, 0x88}, +- {WCD938X_DIGITAL_TX_REQ_FB_CTL_4, 0x88}, +- {WCD938X_DIGITAL_DEM_BYPASS_DATA0, 0x55}, +- {WCD938X_DIGITAL_DEM_BYPASS_DATA1, 0x55}, +- {WCD938X_DIGITAL_DEM_BYPASS_DATA2, 0x55}, +- {WCD938X_DIGITAL_DEM_BYPASS_DATA3, 0x01}, +-}; +- +-static bool wcd938x_rdwr_register(struct device *dev, unsigned int reg) +-{ +- switch (reg) { +- case WCD938X_ANA_PAGE_REGISTER: +- case WCD938X_ANA_BIAS: +- case WCD938X_ANA_RX_SUPPLIES: +- case WCD938X_ANA_HPH: +- case WCD938X_ANA_EAR: +- case WCD938X_ANA_EAR_COMPANDER_CTL: +- case WCD938X_ANA_TX_CH1: +- case WCD938X_ANA_TX_CH2: +- case WCD938X_ANA_TX_CH3: +- case WCD938X_ANA_TX_CH4: +- case WCD938X_ANA_MICB1_MICB2_DSP_EN_LOGIC: +- case WCD938X_ANA_MICB3_DSP_EN_LOGIC: +- case WCD938X_ANA_MBHC_MECH: +- case WCD938X_ANA_MBHC_ELECT: +- case WCD938X_ANA_MBHC_ZDET: +- case WCD938X_ANA_MBHC_BTN0: +- case WCD938X_ANA_MBHC_BTN1: +- case WCD938X_ANA_MBHC_BTN2: +- case WCD938X_ANA_MBHC_BTN3: +- case WCD938X_ANA_MBHC_BTN4: +- case WCD938X_ANA_MBHC_BTN5: +- case WCD938X_ANA_MBHC_BTN6: +- case WCD938X_ANA_MBHC_BTN7: +- case WCD938X_ANA_MICB1: +- case WCD938X_ANA_MICB2: +- case WCD938X_ANA_MICB2_RAMP: +- case WCD938X_ANA_MICB3: +- case WCD938X_ANA_MICB4: +- case WCD938X_BIAS_CTL: +- case WCD938X_BIAS_VBG_FINE_ADJ: +- case WCD938X_LDOL_VDDCX_ADJUST: +- case WCD938X_LDOL_DISABLE_LDOL: +- case WCD938X_MBHC_CTL_CLK: +- case WCD938X_MBHC_CTL_ANA: +- case WCD938X_MBHC_CTL_SPARE_1: +- case WCD938X_MBHC_CTL_SPARE_2: +- case WCD938X_MBHC_CTL_BCS: +- case WCD938X_MBHC_TEST_CTL: +- case WCD938X_LDOH_MODE: +- case WCD938X_LDOH_BIAS: +- case WCD938X_LDOH_STB_LOADS: +- case WCD938X_LDOH_SLOWRAMP: +- case WCD938X_MICB1_TEST_CTL_1: +- case WCD938X_MICB1_TEST_CTL_2: +- case WCD938X_MICB1_TEST_CTL_3: +- case WCD938X_MICB2_TEST_CTL_1: +- case WCD938X_MICB2_TEST_CTL_2: +- case WCD938X_MICB2_TEST_CTL_3: +- case WCD938X_MICB3_TEST_CTL_1: +- case WCD938X_MICB3_TEST_CTL_2: +- case WCD938X_MICB3_TEST_CTL_3: +- case WCD938X_MICB4_TEST_CTL_1: +- case WCD938X_MICB4_TEST_CTL_2: +- case WCD938X_MICB4_TEST_CTL_3: +- case WCD938X_TX_COM_ADC_VCM: +- case WCD938X_TX_COM_BIAS_ATEST: +- case WCD938X_TX_COM_SPARE1: +- case WCD938X_TX_COM_SPARE2: +- case WCD938X_TX_COM_TXFE_DIV_CTL: +- case WCD938X_TX_COM_TXFE_DIV_START: +- case WCD938X_TX_COM_SPARE3: +- case WCD938X_TX_COM_SPARE4: +- case WCD938X_TX_1_2_TEST_EN: +- case WCD938X_TX_1_2_ADC_IB: +- case WCD938X_TX_1_2_ATEST_REFCTL: +- case WCD938X_TX_1_2_TEST_CTL: +- case WCD938X_TX_1_2_TEST_BLK_EN1: +- case WCD938X_TX_1_2_TXFE1_CLKDIV: +- case WCD938X_TX_3_4_TEST_EN: +- case WCD938X_TX_3_4_ADC_IB: +- case WCD938X_TX_3_4_ATEST_REFCTL: +- case WCD938X_TX_3_4_TEST_CTL: +- case WCD938X_TX_3_4_TEST_BLK_EN3: +- case WCD938X_TX_3_4_TXFE3_CLKDIV: +- case WCD938X_TX_3_4_TEST_BLK_EN2: +- case WCD938X_TX_3_4_TXFE2_CLKDIV: +- case WCD938X_TX_3_4_SPARE1: +- case WCD938X_TX_3_4_TEST_BLK_EN4: +- case WCD938X_TX_3_4_TXFE4_CLKDIV: +- case WCD938X_TX_3_4_SPARE2: +- case WCD938X_CLASSH_MODE_1: +- case WCD938X_CLASSH_MODE_2: +- case WCD938X_CLASSH_MODE_3: +- case WCD938X_CLASSH_CTRL_VCL_1: +- case WCD938X_CLASSH_CTRL_VCL_2: +- case WCD938X_CLASSH_CTRL_CCL_1: +- case WCD938X_CLASSH_CTRL_CCL_2: +- case WCD938X_CLASSH_CTRL_CCL_3: +- case WCD938X_CLASSH_CTRL_CCL_4: +- case WCD938X_CLASSH_CTRL_CCL_5: +- case WCD938X_CLASSH_BUCK_TMUX_A_D: +- case WCD938X_CLASSH_BUCK_SW_DRV_CNTL: +- case WCD938X_CLASSH_SPARE: +- case WCD938X_FLYBACK_EN: +- case WCD938X_FLYBACK_VNEG_CTRL_1: +- case WCD938X_FLYBACK_VNEG_CTRL_2: +- case WCD938X_FLYBACK_VNEG_CTRL_3: +- case WCD938X_FLYBACK_VNEG_CTRL_4: +- case WCD938X_FLYBACK_VNEG_CTRL_5: +- case WCD938X_FLYBACK_VNEG_CTRL_6: +- case WCD938X_FLYBACK_VNEG_CTRL_7: +- case WCD938X_FLYBACK_VNEG_CTRL_8: +- case WCD938X_FLYBACK_VNEG_CTRL_9: +- case WCD938X_FLYBACK_VNEGDAC_CTRL_1: +- case WCD938X_FLYBACK_VNEGDAC_CTRL_2: +- case WCD938X_FLYBACK_VNEGDAC_CTRL_3: +- case WCD938X_FLYBACK_CTRL_1: +- case WCD938X_FLYBACK_TEST_CTL: +- case WCD938X_RX_AUX_SW_CTL: +- case WCD938X_RX_PA_AUX_IN_CONN: +- case WCD938X_RX_TIMER_DIV: +- case WCD938X_RX_OCP_CTL: +- case WCD938X_RX_OCP_COUNT: +- case WCD938X_RX_BIAS_EAR_DAC: +- case WCD938X_RX_BIAS_EAR_AMP: +- case WCD938X_RX_BIAS_HPH_LDO: +- case WCD938X_RX_BIAS_HPH_PA: +- case WCD938X_RX_BIAS_HPH_RDACBUFF_CNP2: +- case WCD938X_RX_BIAS_HPH_RDAC_LDO: +- case WCD938X_RX_BIAS_HPH_CNP1: +- case WCD938X_RX_BIAS_HPH_LOWPOWER: +- case WCD938X_RX_BIAS_AUX_DAC: +- case WCD938X_RX_BIAS_AUX_AMP: +- case WCD938X_RX_BIAS_VNEGDAC_BLEEDER: +- case WCD938X_RX_BIAS_MISC: +- case WCD938X_RX_BIAS_BUCK_RST: +- case WCD938X_RX_BIAS_BUCK_VREF_ERRAMP: +- case WCD938X_RX_BIAS_FLYB_ERRAMP: +- case WCD938X_RX_BIAS_FLYB_BUFF: +- case WCD938X_RX_BIAS_FLYB_MID_RST: +- case WCD938X_HPH_CNP_EN: +- case WCD938X_HPH_CNP_WG_CTL: +- case WCD938X_HPH_CNP_WG_TIME: +- case WCD938X_HPH_OCP_CTL: +- case WCD938X_HPH_AUTO_CHOP: +- case WCD938X_HPH_CHOP_CTL: +- case WCD938X_HPH_PA_CTL1: +- case WCD938X_HPH_PA_CTL2: +- case WCD938X_HPH_L_EN: +- case WCD938X_HPH_L_TEST: +- case WCD938X_HPH_L_ATEST: +- case WCD938X_HPH_R_EN: +- case WCD938X_HPH_R_TEST: +- case WCD938X_HPH_R_ATEST: +- case WCD938X_HPH_RDAC_CLK_CTL1: +- case WCD938X_HPH_RDAC_CLK_CTL2: +- case WCD938X_HPH_RDAC_LDO_CTL: +- case WCD938X_HPH_RDAC_CHOP_CLK_LP_CTL: +- case WCD938X_HPH_REFBUFF_UHQA_CTL: +- case WCD938X_HPH_REFBUFF_LP_CTL: +- case WCD938X_HPH_L_DAC_CTL: +- case WCD938X_HPH_R_DAC_CTL: +- case WCD938X_HPH_SURGE_HPHLR_SURGE_COMP_SEL: +- case WCD938X_HPH_SURGE_HPHLR_SURGE_EN: +- case WCD938X_HPH_SURGE_HPHLR_SURGE_MISC1: +- case WCD938X_EAR_EAR_EN_REG: +- case WCD938X_EAR_EAR_PA_CON: +- case WCD938X_EAR_EAR_SP_CON: +- case WCD938X_EAR_EAR_DAC_CON: +- case WCD938X_EAR_EAR_CNP_FSM_CON: +- case WCD938X_EAR_TEST_CTL: +- case WCD938X_ANA_NEW_PAGE_REGISTER: +- case WCD938X_HPH_NEW_ANA_HPH2: +- case WCD938X_HPH_NEW_ANA_HPH3: +- case WCD938X_SLEEP_CTL: +- case WCD938X_SLEEP_WATCHDOG_CTL: +- case WCD938X_MBHC_NEW_ELECT_REM_CLAMP_CTL: +- case WCD938X_MBHC_NEW_CTL_1: +- case WCD938X_MBHC_NEW_CTL_2: +- case WCD938X_MBHC_NEW_PLUG_DETECT_CTL: +- case WCD938X_MBHC_NEW_ZDET_ANA_CTL: +- case WCD938X_MBHC_NEW_ZDET_RAMP_CTL: +- case WCD938X_TX_NEW_AMIC_MUX_CFG: +- case WCD938X_AUX_AUXPA: +- case WCD938X_LDORXTX_MODE: +- case WCD938X_LDORXTX_CONFIG: +- case WCD938X_DIE_CRACK_DIE_CRK_DET_EN: +- case WCD938X_HPH_NEW_INT_RDAC_GAIN_CTL: +- case WCD938X_HPH_NEW_INT_RDAC_HD2_CTL_L: +- case WCD938X_HPH_NEW_INT_RDAC_VREF_CTL: +- case WCD938X_HPH_NEW_INT_RDAC_OVERRIDE_CTL: +- case WCD938X_HPH_NEW_INT_RDAC_HD2_CTL_R: +- case WCD938X_HPH_NEW_INT_PA_MISC1: +- case WCD938X_HPH_NEW_INT_PA_MISC2: +- case WCD938X_HPH_NEW_INT_PA_RDAC_MISC: +- case WCD938X_HPH_NEW_INT_HPH_TIMER1: +- case WCD938X_HPH_NEW_INT_HPH_TIMER2: +- case WCD938X_HPH_NEW_INT_HPH_TIMER3: +- case WCD938X_HPH_NEW_INT_HPH_TIMER4: +- case WCD938X_HPH_NEW_INT_PA_RDAC_MISC2: +- case WCD938X_HPH_NEW_INT_PA_RDAC_MISC3: +- case WCD938X_HPH_NEW_INT_RDAC_HD2_CTL_L_NEW: +- case WCD938X_HPH_NEW_INT_RDAC_HD2_CTL_R_NEW: +- case WCD938X_RX_NEW_INT_HPH_RDAC_BIAS_LOHIFI: +- case WCD938X_RX_NEW_INT_HPH_RDAC_BIAS_ULP: +- case WCD938X_RX_NEW_INT_HPH_RDAC_LDO_LP: +- case WCD938X_MBHC_NEW_INT_MOISTURE_DET_DC_CTRL: +- case WCD938X_MBHC_NEW_INT_MOISTURE_DET_POLLING_CTRL: +- case WCD938X_MBHC_NEW_INT_MECH_DET_CURRENT: +- case WCD938X_MBHC_NEW_INT_SPARE_2: +- case WCD938X_EAR_INT_NEW_EAR_CHOPPER_CON: +- case WCD938X_EAR_INT_NEW_CNP_VCM_CON1: +- case WCD938X_EAR_INT_NEW_CNP_VCM_CON2: +- case WCD938X_EAR_INT_NEW_EAR_DYNAMIC_BIAS: +- case WCD938X_AUX_INT_EN_REG: +- case WCD938X_AUX_INT_PA_CTRL: +- case WCD938X_AUX_INT_SP_CTRL: +- case WCD938X_AUX_INT_DAC_CTRL: +- case WCD938X_AUX_INT_CLK_CTRL: +- case WCD938X_AUX_INT_TEST_CTRL: +- case WCD938X_AUX_INT_MISC: +- case WCD938X_LDORXTX_INT_BIAS: +- case WCD938X_LDORXTX_INT_STB_LOADS_DTEST: +- case WCD938X_LDORXTX_INT_TEST0: +- case WCD938X_LDORXTX_INT_STARTUP_TIMER: +- case WCD938X_LDORXTX_INT_TEST1: +- case WCD938X_SLEEP_INT_WATCHDOG_CTL_1: +- case WCD938X_SLEEP_INT_WATCHDOG_CTL_2: +- case WCD938X_DIE_CRACK_INT_DIE_CRK_DET_INT1: +- case WCD938X_DIE_CRACK_INT_DIE_CRK_DET_INT2: +- case WCD938X_TX_COM_NEW_INT_TXFE_DIVSTOP_L2: +- case WCD938X_TX_COM_NEW_INT_TXFE_DIVSTOP_L1: +- case WCD938X_TX_COM_NEW_INT_TXFE_DIVSTOP_L0: +- case WCD938X_TX_COM_NEW_INT_TXFE_DIVSTOP_ULP1P2M: +- case WCD938X_TX_COM_NEW_INT_TXFE_DIVSTOP_ULP0P6M: +- case WCD938X_TX_COM_NEW_INT_TXFE_ICTRL_STG1_L2L1: +- case WCD938X_TX_COM_NEW_INT_TXFE_ICTRL_STG1_L0: +- case WCD938X_TX_COM_NEW_INT_TXFE_ICTRL_STG1_ULP: +- case WCD938X_TX_COM_NEW_INT_TXFE_ICTRL_STG2MAIN_L2L1: +- case WCD938X_TX_COM_NEW_INT_TXFE_ICTRL_STG2MAIN_L0: +- case WCD938X_TX_COM_NEW_INT_TXFE_ICTRL_STG2MAIN_ULP: +- case WCD938X_TX_COM_NEW_INT_TXFE_ICTRL_STG2CASC_L2L1L0: +- case WCD938X_TX_COM_NEW_INT_TXFE_ICTRL_STG2CASC_ULP: +- case WCD938X_TX_COM_NEW_INT_TXADC_SCBIAS_L2L1: +- case WCD938X_TX_COM_NEW_INT_TXADC_SCBIAS_L0ULP: +- case WCD938X_TX_COM_NEW_INT_TXADC_INT_L2: +- case WCD938X_TX_COM_NEW_INT_TXADC_INT_L1: +- case WCD938X_TX_COM_NEW_INT_TXADC_INT_L0: +- case WCD938X_TX_COM_NEW_INT_TXADC_INT_ULP: +- case WCD938X_DIGITAL_PAGE_REGISTER: +- case WCD938X_DIGITAL_SWR_TX_CLK_RATE: +- case WCD938X_DIGITAL_CDC_RST_CTL: +- case WCD938X_DIGITAL_TOP_CLK_CFG: +- case WCD938X_DIGITAL_CDC_ANA_CLK_CTL: +- case WCD938X_DIGITAL_CDC_DIG_CLK_CTL: +- case WCD938X_DIGITAL_SWR_RST_EN: +- case WCD938X_DIGITAL_CDC_PATH_MODE: +- case WCD938X_DIGITAL_CDC_RX_RST: +- case WCD938X_DIGITAL_CDC_RX0_CTL: +- case WCD938X_DIGITAL_CDC_RX1_CTL: +- case WCD938X_DIGITAL_CDC_RX2_CTL: +- case WCD938X_DIGITAL_CDC_TX_ANA_MODE_0_1: +- case WCD938X_DIGITAL_CDC_TX_ANA_MODE_2_3: +- case WCD938X_DIGITAL_CDC_COMP_CTL_0: +- case WCD938X_DIGITAL_CDC_ANA_TX_CLK_CTL: +- case WCD938X_DIGITAL_CDC_HPH_DSM_A1_0: +- case WCD938X_DIGITAL_CDC_HPH_DSM_A1_1: +- case WCD938X_DIGITAL_CDC_HPH_DSM_A2_0: +- case WCD938X_DIGITAL_CDC_HPH_DSM_A2_1: +- case WCD938X_DIGITAL_CDC_HPH_DSM_A3_0: +- case WCD938X_DIGITAL_CDC_HPH_DSM_A3_1: +- case WCD938X_DIGITAL_CDC_HPH_DSM_A4_0: +- case WCD938X_DIGITAL_CDC_HPH_DSM_A4_1: +- case WCD938X_DIGITAL_CDC_HPH_DSM_A5_0: +- case WCD938X_DIGITAL_CDC_HPH_DSM_A5_1: +- case WCD938X_DIGITAL_CDC_HPH_DSM_A6_0: +- case WCD938X_DIGITAL_CDC_HPH_DSM_A7_0: +- case WCD938X_DIGITAL_CDC_HPH_DSM_C_0: +- case WCD938X_DIGITAL_CDC_HPH_DSM_C_1: +- case WCD938X_DIGITAL_CDC_HPH_DSM_C_2: +- case WCD938X_DIGITAL_CDC_HPH_DSM_C_3: +- case WCD938X_DIGITAL_CDC_HPH_DSM_R1: +- case WCD938X_DIGITAL_CDC_HPH_DSM_R2: +- case WCD938X_DIGITAL_CDC_HPH_DSM_R3: +- case WCD938X_DIGITAL_CDC_HPH_DSM_R4: +- case WCD938X_DIGITAL_CDC_HPH_DSM_R5: +- case WCD938X_DIGITAL_CDC_HPH_DSM_R6: +- case WCD938X_DIGITAL_CDC_HPH_DSM_R7: +- case WCD938X_DIGITAL_CDC_AUX_DSM_A1_0: +- case WCD938X_DIGITAL_CDC_AUX_DSM_A1_1: +- case WCD938X_DIGITAL_CDC_AUX_DSM_A2_0: +- case WCD938X_DIGITAL_CDC_AUX_DSM_A2_1: +- case WCD938X_DIGITAL_CDC_AUX_DSM_A3_0: +- case WCD938X_DIGITAL_CDC_AUX_DSM_A3_1: +- case WCD938X_DIGITAL_CDC_AUX_DSM_A4_0: +- case WCD938X_DIGITAL_CDC_AUX_DSM_A4_1: +- case WCD938X_DIGITAL_CDC_AUX_DSM_A5_0: +- case WCD938X_DIGITAL_CDC_AUX_DSM_A5_1: +- case WCD938X_DIGITAL_CDC_AUX_DSM_A6_0: +- case WCD938X_DIGITAL_CDC_AUX_DSM_A7_0: +- case WCD938X_DIGITAL_CDC_AUX_DSM_C_0: +- case WCD938X_DIGITAL_CDC_AUX_DSM_C_1: +- case WCD938X_DIGITAL_CDC_AUX_DSM_C_2: +- case WCD938X_DIGITAL_CDC_AUX_DSM_C_3: +- case WCD938X_DIGITAL_CDC_AUX_DSM_R1: +- case WCD938X_DIGITAL_CDC_AUX_DSM_R2: +- case WCD938X_DIGITAL_CDC_AUX_DSM_R3: +- case WCD938X_DIGITAL_CDC_AUX_DSM_R4: +- case WCD938X_DIGITAL_CDC_AUX_DSM_R5: +- case WCD938X_DIGITAL_CDC_AUX_DSM_R6: +- case WCD938X_DIGITAL_CDC_AUX_DSM_R7: +- case WCD938X_DIGITAL_CDC_HPH_GAIN_RX_0: +- case WCD938X_DIGITAL_CDC_HPH_GAIN_RX_1: +- case WCD938X_DIGITAL_CDC_HPH_GAIN_DSD_0: +- case WCD938X_DIGITAL_CDC_HPH_GAIN_DSD_1: +- case WCD938X_DIGITAL_CDC_HPH_GAIN_DSD_2: +- case WCD938X_DIGITAL_CDC_AUX_GAIN_DSD_0: +- case WCD938X_DIGITAL_CDC_AUX_GAIN_DSD_1: +- case WCD938X_DIGITAL_CDC_AUX_GAIN_DSD_2: +- case WCD938X_DIGITAL_CDC_HPH_GAIN_CTL: +- case WCD938X_DIGITAL_CDC_AUX_GAIN_CTL: +- case WCD938X_DIGITAL_CDC_EAR_PATH_CTL: +- case WCD938X_DIGITAL_CDC_SWR_CLH: +- case WCD938X_DIGITAL_SWR_CLH_BYP: +- case WCD938X_DIGITAL_CDC_TX0_CTL: +- case WCD938X_DIGITAL_CDC_TX1_CTL: +- case WCD938X_DIGITAL_CDC_TX2_CTL: +- case WCD938X_DIGITAL_CDC_TX_RST: +- case WCD938X_DIGITAL_CDC_REQ_CTL: +- case WCD938X_DIGITAL_CDC_RST: +- case WCD938X_DIGITAL_CDC_AMIC_CTL: +- case WCD938X_DIGITAL_CDC_DMIC_CTL: +- case WCD938X_DIGITAL_CDC_DMIC1_CTL: +- case WCD938X_DIGITAL_CDC_DMIC2_CTL: +- case WCD938X_DIGITAL_CDC_DMIC3_CTL: +- case WCD938X_DIGITAL_CDC_DMIC4_CTL: +- case WCD938X_DIGITAL_EFUSE_PRG_CTL: +- case WCD938X_DIGITAL_EFUSE_CTL: +- case WCD938X_DIGITAL_CDC_DMIC_RATE_1_2: +- case WCD938X_DIGITAL_CDC_DMIC_RATE_3_4: +- case WCD938X_DIGITAL_PDM_WD_CTL0: +- case WCD938X_DIGITAL_PDM_WD_CTL1: +- case WCD938X_DIGITAL_PDM_WD_CTL2: +- case WCD938X_DIGITAL_INTR_MODE: +- case WCD938X_DIGITAL_INTR_MASK_0: +- case WCD938X_DIGITAL_INTR_MASK_1: +- case WCD938X_DIGITAL_INTR_MASK_2: +- case WCD938X_DIGITAL_INTR_CLEAR_0: +- case WCD938X_DIGITAL_INTR_CLEAR_1: +- case WCD938X_DIGITAL_INTR_CLEAR_2: +- case WCD938X_DIGITAL_INTR_LEVEL_0: +- case WCD938X_DIGITAL_INTR_LEVEL_1: +- case WCD938X_DIGITAL_INTR_LEVEL_2: +- case WCD938X_DIGITAL_INTR_SET_0: +- case WCD938X_DIGITAL_INTR_SET_1: +- case WCD938X_DIGITAL_INTR_SET_2: +- case WCD938X_DIGITAL_INTR_TEST_0: +- case WCD938X_DIGITAL_INTR_TEST_1: +- case WCD938X_DIGITAL_INTR_TEST_2: +- case WCD938X_DIGITAL_TX_MODE_DBG_EN: +- case WCD938X_DIGITAL_TX_MODE_DBG_0_1: +- case WCD938X_DIGITAL_TX_MODE_DBG_2_3: +- case WCD938X_DIGITAL_LB_IN_SEL_CTL: +- case WCD938X_DIGITAL_LOOP_BACK_MODE: +- case WCD938X_DIGITAL_SWR_DAC_TEST: +- case WCD938X_DIGITAL_SWR_HM_TEST_RX_0: +- case WCD938X_DIGITAL_SWR_HM_TEST_TX_0: +- case WCD938X_DIGITAL_SWR_HM_TEST_RX_1: +- case WCD938X_DIGITAL_SWR_HM_TEST_TX_1: +- case WCD938X_DIGITAL_SWR_HM_TEST_TX_2: +- case WCD938X_DIGITAL_PAD_CTL_SWR_0: +- case WCD938X_DIGITAL_PAD_CTL_SWR_1: +- case WCD938X_DIGITAL_I2C_CTL: +- case WCD938X_DIGITAL_CDC_TX_TANGGU_SW_MODE: +- case WCD938X_DIGITAL_EFUSE_TEST_CTL_0: +- case WCD938X_DIGITAL_EFUSE_TEST_CTL_1: +- case WCD938X_DIGITAL_PAD_CTL_PDM_RX0: +- case WCD938X_DIGITAL_PAD_CTL_PDM_RX1: +- case WCD938X_DIGITAL_PAD_CTL_PDM_TX0: +- case WCD938X_DIGITAL_PAD_CTL_PDM_TX1: +- case WCD938X_DIGITAL_PAD_CTL_PDM_TX2: +- case WCD938X_DIGITAL_PAD_INP_DIS_0: +- case WCD938X_DIGITAL_PAD_INP_DIS_1: +- case WCD938X_DIGITAL_DRIVE_STRENGTH_0: +- case WCD938X_DIGITAL_DRIVE_STRENGTH_1: +- case WCD938X_DIGITAL_DRIVE_STRENGTH_2: +- case WCD938X_DIGITAL_RX_DATA_EDGE_CTL: +- case WCD938X_DIGITAL_TX_DATA_EDGE_CTL: +- case WCD938X_DIGITAL_GPIO_MODE: +- case WCD938X_DIGITAL_PIN_CTL_OE: +- case WCD938X_DIGITAL_PIN_CTL_DATA_0: +- case WCD938X_DIGITAL_PIN_CTL_DATA_1: +- case WCD938X_DIGITAL_DIG_DEBUG_CTL: +- case WCD938X_DIGITAL_DIG_DEBUG_EN: +- case WCD938X_DIGITAL_ANA_CSR_DBG_ADD: +- case WCD938X_DIGITAL_ANA_CSR_DBG_CTL: +- case WCD938X_DIGITAL_SSP_DBG: +- case WCD938X_DIGITAL_SPARE_0: +- case WCD938X_DIGITAL_SPARE_1: +- case WCD938X_DIGITAL_SPARE_2: +- case WCD938X_DIGITAL_TX_REQ_FB_CTL_0: +- case WCD938X_DIGITAL_TX_REQ_FB_CTL_1: +- case WCD938X_DIGITAL_TX_REQ_FB_CTL_2: +- case WCD938X_DIGITAL_TX_REQ_FB_CTL_3: +- case WCD938X_DIGITAL_TX_REQ_FB_CTL_4: +- case WCD938X_DIGITAL_DEM_BYPASS_DATA0: +- case WCD938X_DIGITAL_DEM_BYPASS_DATA1: +- case WCD938X_DIGITAL_DEM_BYPASS_DATA2: +- case WCD938X_DIGITAL_DEM_BYPASS_DATA3: +- return true; +- } +- +- return false; +-} +- +-static bool wcd938x_readonly_register(struct device *dev, unsigned int reg) +-{ +- switch (reg) { +- case WCD938X_ANA_MBHC_RESULT_1: +- case WCD938X_ANA_MBHC_RESULT_2: +- case WCD938X_ANA_MBHC_RESULT_3: +- case WCD938X_MBHC_MOISTURE_DET_FSM_STATUS: +- case WCD938X_TX_1_2_SAR2_ERR: +- case WCD938X_TX_1_2_SAR1_ERR: +- case WCD938X_TX_3_4_SAR4_ERR: +- case WCD938X_TX_3_4_SAR3_ERR: +- case WCD938X_HPH_L_STATUS: +- case WCD938X_HPH_R_STATUS: +- case WCD938X_HPH_SURGE_HPHLR_SURGE_STATUS: +- case WCD938X_EAR_STATUS_REG_1: +- case WCD938X_EAR_STATUS_REG_2: +- case WCD938X_MBHC_NEW_FSM_STATUS: +- case WCD938X_MBHC_NEW_ADC_RESULT: +- case WCD938X_DIE_CRACK_DIE_CRK_DET_OUT: +- case WCD938X_AUX_INT_STATUS_REG: +- case WCD938X_LDORXTX_INT_STATUS: +- case WCD938X_DIGITAL_CHIP_ID0: +- case WCD938X_DIGITAL_CHIP_ID1: +- case WCD938X_DIGITAL_CHIP_ID2: +- case WCD938X_DIGITAL_CHIP_ID3: +- case WCD938X_DIGITAL_INTR_STATUS_0: +- case WCD938X_DIGITAL_INTR_STATUS_1: +- case WCD938X_DIGITAL_INTR_STATUS_2: +- case WCD938X_DIGITAL_INTR_CLEAR_0: +- case WCD938X_DIGITAL_INTR_CLEAR_1: +- case WCD938X_DIGITAL_INTR_CLEAR_2: +- case WCD938X_DIGITAL_SWR_HM_TEST_0: +- case WCD938X_DIGITAL_SWR_HM_TEST_1: +- case WCD938X_DIGITAL_EFUSE_T_DATA_0: +- case WCD938X_DIGITAL_EFUSE_T_DATA_1: +- case WCD938X_DIGITAL_PIN_STATUS_0: +- case WCD938X_DIGITAL_PIN_STATUS_1: +- case WCD938X_DIGITAL_MODE_STATUS_0: +- case WCD938X_DIGITAL_MODE_STATUS_1: +- case WCD938X_DIGITAL_EFUSE_REG_0: +- case WCD938X_DIGITAL_EFUSE_REG_1: +- case WCD938X_DIGITAL_EFUSE_REG_2: +- case WCD938X_DIGITAL_EFUSE_REG_3: +- case WCD938X_DIGITAL_EFUSE_REG_4: +- case WCD938X_DIGITAL_EFUSE_REG_5: +- case WCD938X_DIGITAL_EFUSE_REG_6: +- case WCD938X_DIGITAL_EFUSE_REG_7: +- case WCD938X_DIGITAL_EFUSE_REG_8: +- case WCD938X_DIGITAL_EFUSE_REG_9: +- case WCD938X_DIGITAL_EFUSE_REG_10: +- case WCD938X_DIGITAL_EFUSE_REG_11: +- case WCD938X_DIGITAL_EFUSE_REG_12: +- case WCD938X_DIGITAL_EFUSE_REG_13: +- case WCD938X_DIGITAL_EFUSE_REG_14: +- case WCD938X_DIGITAL_EFUSE_REG_15: +- case WCD938X_DIGITAL_EFUSE_REG_16: +- case WCD938X_DIGITAL_EFUSE_REG_17: +- case WCD938X_DIGITAL_EFUSE_REG_18: +- case WCD938X_DIGITAL_EFUSE_REG_19: +- case WCD938X_DIGITAL_EFUSE_REG_20: +- case WCD938X_DIGITAL_EFUSE_REG_21: +- case WCD938X_DIGITAL_EFUSE_REG_22: +- case WCD938X_DIGITAL_EFUSE_REG_23: +- case WCD938X_DIGITAL_EFUSE_REG_24: +- case WCD938X_DIGITAL_EFUSE_REG_25: +- case WCD938X_DIGITAL_EFUSE_REG_26: +- case WCD938X_DIGITAL_EFUSE_REG_27: +- case WCD938X_DIGITAL_EFUSE_REG_28: +- case WCD938X_DIGITAL_EFUSE_REG_29: +- case WCD938X_DIGITAL_EFUSE_REG_30: +- case WCD938X_DIGITAL_EFUSE_REG_31: +- return true; +- } +- return false; +-} +- +-static bool wcd938x_readable_register(struct device *dev, unsigned int reg) +-{ +- bool ret; +- +- ret = wcd938x_readonly_register(dev, reg); +- if (!ret) +- return wcd938x_rdwr_register(dev, reg); +- +- return ret; +-} +- +-static bool wcd938x_writeable_register(struct device *dev, unsigned int reg) +-{ +- return wcd938x_rdwr_register(dev, reg); +-} +- +-static bool wcd938x_volatile_register(struct device *dev, unsigned int reg) +-{ +- if (reg <= WCD938X_BASE_ADDRESS) +- return false; +- +- if (reg == WCD938X_DIGITAL_SWR_TX_CLK_RATE) +- return true; +- +- if (wcd938x_readonly_register(dev, reg)) +- return true; +- +- return false; +-} +- +-static struct regmap_config wcd938x_regmap_config = { +- .name = "wcd938x_csr", +- .reg_bits = 32, +- .val_bits = 8, +- .cache_type = REGCACHE_RBTREE, +- .reg_defaults = wcd938x_defaults, +- .num_reg_defaults = ARRAY_SIZE(wcd938x_defaults), +- .max_register = WCD938X_MAX_REGISTER, +- .readable_reg = wcd938x_readable_register, +- .writeable_reg = wcd938x_writeable_register, +- .volatile_reg = wcd938x_volatile_register, +- .can_multi_write = true, +-}; +- + static const struct regmap_irq wcd938x_irqs[WCD938X_NUM_IRQS] = { + REGMAP_IRQ_REG(WCD938X_IRQ_MBHC_BUTTON_PRESS_DET, 0, 0x01), + REGMAP_IRQ_REG(WCD938X_IRQ_MBHC_BUTTON_RELEASE_DET, 0, 0x02), +@@ -4445,10 +3450,10 @@ static int wcd938x_bind(struct device *dev) + return -EINVAL; + } + +- wcd938x->regmap = devm_regmap_init_sdw(wcd938x->tx_sdw_dev, &wcd938x_regmap_config); +- if (IS_ERR(wcd938x->regmap)) { +- dev_err(dev, "%s: tx csr regmap not found\n", __func__); +- return PTR_ERR(wcd938x->regmap); ++ wcd938x->regmap = dev_get_regmap(&wcd938x->tx_sdw_dev->dev, NULL); ++ if (!wcd938x->regmap) { ++ dev_err(dev, "could not get TX device regmap\n"); ++ return -EINVAL; + } + + ret = wcd938x_irq_init(wcd938x, dev); +diff --git a/sound/soc/codecs/wcd938x.h b/sound/soc/codecs/wcd938x.h +index ea82039e78435..74b1498fec38b 100644 +--- a/sound/soc/codecs/wcd938x.h ++++ b/sound/soc/codecs/wcd938x.h +@@ -663,6 +663,7 @@ struct wcd938x_sdw_priv { + bool is_tx; + struct wcd938x_priv *wcd938x; + struct irq_domain *slave_irq; ++ struct regmap *regmap; + }; + + #if IS_ENABLED(CONFIG_SND_SOC_WCD938X_SDW) +-- +2.42.0 + diff --git a/queue-5.15/asoc-codecs-wcd938x-fix-regulator-leaks-on-probe-err.patch b/queue-5.15/asoc-codecs-wcd938x-fix-regulator-leaks-on-probe-err.patch new file mode 100644 index 00000000000..6b48b9a1240 --- /dev/null +++ b/queue-5.15/asoc-codecs-wcd938x-fix-regulator-leaks-on-probe-err.patch @@ -0,0 +1,80 @@ +From 7e30e3c7254ed812e9835adf6b2f4bbec70d1d80 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 3 Oct 2023 17:55:55 +0200 +Subject: ASoC: codecs: wcd938x: fix regulator leaks on probe errors + +From: Johan Hovold + +[ Upstream commit 69a026a2357ee69983690d07976de44ef26ee38a ] + +Make sure to disable and free the regulators on probe errors and on +driver unbind. + +Fixes: 16572522aece ("ASoC: codecs: wcd938x-sdw: add SoundWire driver") +Cc: stable@vger.kernel.org # 5.14 +Cc: Srinivas Kandagatla +Signed-off-by: Johan Hovold +Link: https://lore.kernel.org/r/20231003155558.27079-5-johan+linaro@kernel.org +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + sound/soc/codecs/wcd938x.c | 18 +++++++++++++++--- + 1 file changed, 15 insertions(+), 3 deletions(-) + +diff --git a/sound/soc/codecs/wcd938x.c b/sound/soc/codecs/wcd938x.c +index ea86f04641b8a..5cf780dc333f6 100644 +--- a/sound/soc/codecs/wcd938x.c ++++ b/sound/soc/codecs/wcd938x.c +@@ -3300,8 +3300,10 @@ static int wcd938x_populate_dt_data(struct wcd938x_priv *wcd938x, struct device + return dev_err_probe(dev, ret, "Failed to get supplies\n"); + + ret = regulator_bulk_enable(WCD938X_MAX_SUPPLY, wcd938x->supplies); +- if (ret) ++ if (ret) { ++ regulator_bulk_free(WCD938X_MAX_SUPPLY, wcd938x->supplies); + return dev_err_probe(dev, ret, "Failed to enable supplies\n"); ++ } + + wcd938x_dt_parse_micbias_info(dev, wcd938x); + +@@ -3577,13 +3579,13 @@ static int wcd938x_probe(struct platform_device *pdev) + + ret = wcd938x_add_slave_components(wcd938x, dev, &match); + if (ret) +- return ret; ++ goto err_disable_regulators; + + wcd938x_reset(wcd938x); + + ret = component_master_add_with_match(dev, &wcd938x_comp_ops, match); + if (ret) +- return ret; ++ goto err_disable_regulators; + + pm_runtime_set_autosuspend_delay(dev, 1000); + pm_runtime_use_autosuspend(dev); +@@ -3593,11 +3595,21 @@ static int wcd938x_probe(struct platform_device *pdev) + pm_runtime_idle(dev); + + return 0; ++ ++err_disable_regulators: ++ regulator_bulk_disable(WCD938X_MAX_SUPPLY, wcd938x->supplies); ++ regulator_bulk_free(WCD938X_MAX_SUPPLY, wcd938x->supplies); ++ ++ return ret; + } + + static void wcd938x_remove(struct platform_device *pdev) + { ++ struct wcd938x_priv *wcd938x = dev_get_drvdata(&pdev->dev); ++ + component_master_del(&pdev->dev, &wcd938x_comp_ops); ++ regulator_bulk_disable(WCD938X_MAX_SUPPLY, wcd938x->supplies); ++ regulator_bulk_free(WCD938X_MAX_SUPPLY, wcd938x->supplies); + } + + #if defined(CONFIG_OF) +-- +2.42.0 + diff --git a/queue-5.15/asoc-codecs-wcd938x-fix-resource-leaks-on-bind-error.patch b/queue-5.15/asoc-codecs-wcd938x-fix-resource-leaks-on-bind-error.patch new file mode 100644 index 00000000000..a41a538fc2c --- /dev/null +++ b/queue-5.15/asoc-codecs-wcd938x-fix-resource-leaks-on-bind-error.patch @@ -0,0 +1,138 @@ +From 3313465836cea8838b025d092e711ebcd4926d85 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 3 Oct 2023 17:55:54 +0200 +Subject: ASoC: codecs: wcd938x: fix resource leaks on bind errors + +From: Johan Hovold + +[ Upstream commit da29b94ed3547cee9d510d02eca4009f2de476cf ] + +Add the missing code to release resources on bind errors, including the +references taken by wcd938x_sdw_device_get() which also need to be +dropped on unbind(). + +Fixes: 16572522aece ("ASoC: codecs: wcd938x-sdw: add SoundWire driver") +Cc: stable@vger.kernel.org # 5.14 +Cc: Srinivas Kandagatla +Signed-off-by: Johan Hovold +Link: https://lore.kernel.org/r/20231003155558.27079-4-johan+linaro@kernel.org +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + sound/soc/codecs/wcd938x.c | 44 +++++++++++++++++++++++++++++--------- + 1 file changed, 34 insertions(+), 10 deletions(-) + +diff --git a/sound/soc/codecs/wcd938x.c b/sound/soc/codecs/wcd938x.c +index 16e2e1c186846..e68992b704cfa 100644 +--- a/sound/soc/codecs/wcd938x.c ++++ b/sound/soc/codecs/wcd938x.c +@@ -3416,7 +3416,8 @@ static int wcd938x_bind(struct device *dev) + wcd938x->rxdev = wcd938x_sdw_device_get(wcd938x->rxnode); + if (!wcd938x->rxdev) { + dev_err(dev, "could not find slave with matching of node\n"); +- return -EINVAL; ++ ret = -EINVAL; ++ goto err_unbind; + } + wcd938x->sdw_priv[AIF1_PB] = dev_get_drvdata(wcd938x->rxdev); + wcd938x->sdw_priv[AIF1_PB]->wcd938x = wcd938x; +@@ -3424,7 +3425,8 @@ static int wcd938x_bind(struct device *dev) + wcd938x->txdev = wcd938x_sdw_device_get(wcd938x->txnode); + if (!wcd938x->txdev) { + dev_err(dev, "could not find txslave with matching of node\n"); +- return -EINVAL; ++ ret = -EINVAL; ++ goto err_put_rxdev; + } + wcd938x->sdw_priv[AIF1_CAP] = dev_get_drvdata(wcd938x->txdev); + wcd938x->sdw_priv[AIF1_CAP]->wcd938x = wcd938x; +@@ -3435,31 +3437,35 @@ static int wcd938x_bind(struct device *dev) + if (!device_link_add(wcd938x->rxdev, wcd938x->txdev, DL_FLAG_STATELESS | + DL_FLAG_PM_RUNTIME)) { + dev_err(dev, "could not devlink tx and rx\n"); +- return -EINVAL; ++ ret = -EINVAL; ++ goto err_put_txdev; + } + + if (!device_link_add(dev, wcd938x->txdev, DL_FLAG_STATELESS | + DL_FLAG_PM_RUNTIME)) { + dev_err(dev, "could not devlink wcd and tx\n"); +- return -EINVAL; ++ ret = -EINVAL; ++ goto err_remove_rxtx_link; + } + + if (!device_link_add(dev, wcd938x->rxdev, DL_FLAG_STATELESS | + DL_FLAG_PM_RUNTIME)) { + dev_err(dev, "could not devlink wcd and rx\n"); +- return -EINVAL; ++ ret = -EINVAL; ++ goto err_remove_tx_link; + } + + wcd938x->regmap = dev_get_regmap(&wcd938x->tx_sdw_dev->dev, NULL); + if (!wcd938x->regmap) { + dev_err(dev, "could not get TX device regmap\n"); +- return -EINVAL; ++ ret = -EINVAL; ++ goto err_remove_rx_link; + } + + ret = wcd938x_irq_init(wcd938x, dev); + if (ret) { + dev_err(dev, "%s: IRQ init failed: %d\n", __func__, ret); +- return ret; ++ goto err_remove_rx_link; + } + + wcd938x->sdw_priv[AIF1_PB]->slave_irq = wcd938x->virq; +@@ -3468,17 +3474,33 @@ static int wcd938x_bind(struct device *dev) + ret = wcd938x_set_micbias_data(wcd938x); + if (ret < 0) { + dev_err(dev, "%s: bad micbias pdata\n", __func__); +- return ret; ++ goto err_remove_rx_link; + } + + ret = snd_soc_register_component(dev, &soc_codec_dev_wcd938x, + wcd938x_dais, ARRAY_SIZE(wcd938x_dais)); +- if (ret) ++ if (ret) { + dev_err(dev, "%s: Codec registration failed\n", + __func__); ++ goto err_remove_rx_link; ++ } + +- return ret; ++ return 0; + ++err_remove_rx_link: ++ device_link_remove(dev, wcd938x->rxdev); ++err_remove_tx_link: ++ device_link_remove(dev, wcd938x->txdev); ++err_remove_rxtx_link: ++ device_link_remove(wcd938x->rxdev, wcd938x->txdev); ++err_put_txdev: ++ put_device(wcd938x->txdev); ++err_put_rxdev: ++ put_device(wcd938x->rxdev); ++err_unbind: ++ component_unbind_all(dev, wcd938x); ++ ++ return ret; + } + + static void wcd938x_unbind(struct device *dev) +@@ -3489,6 +3511,8 @@ static void wcd938x_unbind(struct device *dev) + device_link_remove(dev, wcd938x->txdev); + device_link_remove(dev, wcd938x->rxdev); + device_link_remove(wcd938x->rxdev, wcd938x->txdev); ++ put_device(wcd938x->txdev); ++ put_device(wcd938x->rxdev); + component_unbind_all(dev, wcd938x); + } + +-- +2.42.0 + diff --git a/queue-5.15/asoc-codecs-wcd938x-fix-runtime-pm-imbalance-on-remo.patch b/queue-5.15/asoc-codecs-wcd938x-fix-runtime-pm-imbalance-on-remo.patch new file mode 100644 index 00000000000..25e0c75e057 --- /dev/null +++ b/queue-5.15/asoc-codecs-wcd938x-fix-runtime-pm-imbalance-on-remo.patch @@ -0,0 +1,48 @@ +From 91a14cfc96c1f13e42be7645624f554b8382fde1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 3 Oct 2023 17:55:56 +0200 +Subject: ASoC: codecs: wcd938x: fix runtime PM imbalance on remove + +From: Johan Hovold + +[ Upstream commit 3ebebb2c1eca92a15107b2d7aeff34196fd9e217 ] + +Make sure to balance the runtime PM operations, including the disable +count, on driver unbind. + +Fixes: 16572522aece ("ASoC: codecs: wcd938x-sdw: add SoundWire driver") +Cc: stable@vger.kernel.org # 5.14 +Cc: Srinivas Kandagatla +Signed-off-by: Johan Hovold +Link: https://lore.kernel.org/r/20231003155558.27079-6-johan+linaro@kernel.org +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + sound/soc/codecs/wcd938x.c | 10 ++++++++-- + 1 file changed, 8 insertions(+), 2 deletions(-) + +diff --git a/sound/soc/codecs/wcd938x.c b/sound/soc/codecs/wcd938x.c +index 5cf780dc333f6..ccfdb571fd3af 100644 +--- a/sound/soc/codecs/wcd938x.c ++++ b/sound/soc/codecs/wcd938x.c +@@ -3605,9 +3605,15 @@ static int wcd938x_probe(struct platform_device *pdev) + + static void wcd938x_remove(struct platform_device *pdev) + { +- struct wcd938x_priv *wcd938x = dev_get_drvdata(&pdev->dev); ++ struct device *dev = &pdev->dev; ++ struct wcd938x_priv *wcd938x = dev_get_drvdata(dev); ++ ++ component_master_del(dev, &wcd938x_comp_ops); ++ ++ pm_runtime_disable(dev); ++ pm_runtime_set_suspended(dev); ++ pm_runtime_dont_use_autosuspend(dev); + +- component_master_del(&pdev->dev, &wcd938x_comp_ops); + regulator_bulk_disable(WCD938X_MAX_SUPPLY, wcd938x->supplies); + regulator_bulk_free(WCD938X_MAX_SUPPLY, wcd938x->supplies); + } +-- +2.42.0 + diff --git a/queue-5.15/asoc-codecs-wcd938x-simplify-with-dev_err_probe.patch b/queue-5.15/asoc-codecs-wcd938x-simplify-with-dev_err_probe.patch new file mode 100644 index 00000000000..cae4a30e314 --- /dev/null +++ b/queue-5.15/asoc-codecs-wcd938x-simplify-with-dev_err_probe.patch @@ -0,0 +1,65 @@ +From 6ed2624f72fe0382dd3628c1e76add6cf246e480 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 18 Apr 2023 09:46:30 +0200 +Subject: ASoC: codecs: wcd938x: Simplify with dev_err_probe + +From: Krzysztof Kozlowski + +[ Upstream commit 60ba2fda5280528e70fa26b44e36d1530f6d1d7e ] + +Replace dev_err() in probe() path with dev_err_probe() to: +1. Make code a bit simpler and easier to read, +2. Do not print messages on deferred probe. + +Signed-off-by: Krzysztof Kozlowski +Link: https://lore.kernel.org/r/20230418074630.8681-4-krzysztof.kozlowski@linaro.org +Signed-off-by: Mark Brown +Stable-dep-of: 69a026a2357e ("ASoC: codecs: wcd938x: fix regulator leaks on probe errors") +Signed-off-by: Sasha Levin +--- + sound/soc/codecs/wcd938x.c | 20 +++++++------------- + 1 file changed, 7 insertions(+), 13 deletions(-) + +diff --git a/sound/soc/codecs/wcd938x.c b/sound/soc/codecs/wcd938x.c +index 00538cf86b87f..ea86f04641b8a 100644 +--- a/sound/soc/codecs/wcd938x.c ++++ b/sound/soc/codecs/wcd938x.c +@@ -3286,11 +3286,9 @@ static int wcd938x_populate_dt_data(struct wcd938x_priv *wcd938x, struct device + int ret; + + wcd938x->reset_gpio = of_get_named_gpio(dev->of_node, "reset-gpios", 0); +- if (wcd938x->reset_gpio < 0) { +- dev_err(dev, "Failed to get reset gpio: err = %d\n", +- wcd938x->reset_gpio); +- return wcd938x->reset_gpio; +- } ++ if (wcd938x->reset_gpio < 0) ++ return dev_err_probe(dev, wcd938x->reset_gpio, ++ "Failed to get reset gpio\n"); + + wcd938x->supplies[0].supply = "vdd-rxtx"; + wcd938x->supplies[1].supply = "vdd-io"; +@@ -3298,16 +3296,12 @@ static int wcd938x_populate_dt_data(struct wcd938x_priv *wcd938x, struct device + wcd938x->supplies[3].supply = "vdd-mic-bias"; + + ret = regulator_bulk_get(dev, WCD938X_MAX_SUPPLY, wcd938x->supplies); +- if (ret) { +- dev_err(dev, "Failed to get supplies: err = %d\n", ret); +- return ret; +- } ++ if (ret) ++ return dev_err_probe(dev, ret, "Failed to get supplies\n"); + + ret = regulator_bulk_enable(WCD938X_MAX_SUPPLY, wcd938x->supplies); +- if (ret) { +- dev_err(dev, "Failed to enable supplies: err = %d\n", ret); +- return ret; +- } ++ if (ret) ++ return dev_err_probe(dev, ret, "Failed to enable supplies\n"); + + wcd938x_dt_parse_micbias_info(dev, wcd938x); + +-- +2.42.0 + diff --git a/queue-5.15/asoc-rt1318-add-rt1318-sdca-vendor-specific-driver.patch b/queue-5.15/asoc-rt1318-add-rt1318-sdca-vendor-specific-driver.patch new file mode 100644 index 00000000000..9805d307470 --- /dev/null +++ b/queue-5.15/asoc-rt1318-add-rt1318-sdca-vendor-specific-driver.patch @@ -0,0 +1,1069 @@ +From 5916f2b7fe364af68f13896cbfbd0b9c3df8c2b0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 8 Nov 2022 17:27:27 +0800 +Subject: ASoC: rt1318: Add RT1318 SDCA vendor-specific driver + +From: Shuming Fan + +[ Upstream commit 6ad73a2b42ea6d43fc5bf32033e8f6b21df3109e ] + +This is the initial amplifier driver for rt1318 SDCA version. + +Signed-off-by: Shuming Fan +Link: https://lore.kernel.org/r/20221108092727.13011-1-shumingf@realtek.com +Signed-off-by: Mark Brown +Stable-dep-of: da29b94ed354 ("ASoC: codecs: wcd938x: fix resource leaks on bind errors") +Signed-off-by: Sasha Levin +--- + sound/soc/codecs/Kconfig | 6 + + sound/soc/codecs/Makefile | 2 + + sound/soc/codecs/rt1318-sdw.c | 884 ++++++++++++++++++++++++++++++++++ + sound/soc/codecs/rt1318-sdw.h | 101 ++++ + 4 files changed, 993 insertions(+) + create mode 100644 sound/soc/codecs/rt1318-sdw.c + create mode 100644 sound/soc/codecs/rt1318-sdw.h + +diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig +index 31896c8c2b0d6..4c7c01f0e77a2 100644 +--- a/sound/soc/codecs/Kconfig ++++ b/sound/soc/codecs/Kconfig +@@ -187,6 +187,7 @@ config SND_SOC_ALL_CODECS + imply SND_SOC_RT715_SDCA_SDW + imply SND_SOC_RT1308_SDW + imply SND_SOC_RT1316_SDW ++ imply SND_SOC_RT1318_SDW + imply SND_SOC_RT9120 + imply SND_SOC_SDW_MOCKUP + imply SND_SOC_SGTL5000 +@@ -1173,6 +1174,11 @@ config SND_SOC_RT1316_SDW + depends on SOUNDWIRE + select REGMAP_SOUNDWIRE + ++config SND_SOC_RT1318_SDW ++ tristate "Realtek RT1318 Codec - SDW" ++ depends on SOUNDWIRE ++ select REGMAP_SOUNDWIRE ++ + config SND_SOC_RT5514 + tristate + depends on I2C +diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile +index 4edc4775c7323..12adfbf048a2a 100644 +--- a/sound/soc/codecs/Makefile ++++ b/sound/soc/codecs/Makefile +@@ -177,6 +177,7 @@ snd-soc-rt1305-objs := rt1305.o + snd-soc-rt1308-objs := rt1308.o + snd-soc-rt1308-sdw-objs := rt1308-sdw.o + snd-soc-rt1316-sdw-objs := rt1316-sdw.o ++snd-soc-rt1318-sdw-objs := rt1318-sdw.o + snd-soc-rt274-objs := rt274.o + snd-soc-rt286-objs := rt286.o + snd-soc-rt298-objs := rt298.o +@@ -506,6 +507,7 @@ obj-$(CONFIG_SND_SOC_RT1305) += snd-soc-rt1305.o + obj-$(CONFIG_SND_SOC_RT1308) += snd-soc-rt1308.o + obj-$(CONFIG_SND_SOC_RT1308_SDW) += snd-soc-rt1308-sdw.o + obj-$(CONFIG_SND_SOC_RT1316_SDW) += snd-soc-rt1316-sdw.o ++obj-$(CONFIG_SND_SOC_RT1318_SDW) += snd-soc-rt1318-sdw.o + obj-$(CONFIG_SND_SOC_RT274) += snd-soc-rt274.o + obj-$(CONFIG_SND_SOC_RT286) += snd-soc-rt286.o + obj-$(CONFIG_SND_SOC_RT298) += snd-soc-rt298.o +diff --git a/sound/soc/codecs/rt1318-sdw.c b/sound/soc/codecs/rt1318-sdw.c +new file mode 100644 +index 0000000000000..f85f5ab2c6d04 +--- /dev/null ++++ b/sound/soc/codecs/rt1318-sdw.c +@@ -0,0 +1,884 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++// ++// rt1318-sdw.c -- rt1318 SDCA ALSA SoC amplifier audio driver ++// ++// Copyright(c) 2022 Realtek Semiconductor Corp. ++// ++// ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "rt1318-sdw.h" ++ ++static const struct reg_sequence rt1318_blind_write[] = { ++ { 0xc001, 0x43 }, ++ { 0xc003, 0xa2 }, ++ { 0xc004, 0x44 }, ++ { 0xc005, 0x44 }, ++ { 0xc006, 0x33 }, ++ { 0xc007, 0x64 }, ++ { 0xc320, 0x20 }, ++ { 0xf203, 0x18 }, ++ { 0xf211, 0x00 }, ++ { 0xf212, 0x26 }, ++ { 0xf20d, 0x17 }, ++ { 0xf214, 0x06 }, ++ { 0xf20e, 0x00 }, ++ { 0xf223, 0x7f }, ++ { 0xf224, 0xdb }, ++ { 0xf225, 0xee }, ++ { 0xf226, 0x3f }, ++ { 0xf227, 0x0f }, ++ { 0xf21a, 0x78 }, ++ { 0xf242, 0x3c }, ++ { 0xc321, 0x0b }, ++ { 0xc200, 0xd8 }, ++ { 0xc201, 0x27 }, ++ { 0xc202, 0x0f }, ++ { 0xf800, 0x20 }, ++ { 0xdf00, 0x10 }, ++ { 0xdf5f, 0x01 }, ++ { 0xdf60, 0xa7 }, ++ { 0xc400, 0x0e }, ++ { 0xc401, 0x43 }, ++ { 0xc402, 0xe0 }, ++ { 0xc403, 0x00 }, ++ { 0xc404, 0x4c }, ++ { 0xc407, 0x02 }, ++ { 0xc408, 0x3f }, ++ { 0xc300, 0x01 }, ++ { 0xc206, 0x78 }, ++ { 0xc203, 0x84 }, ++ { 0xc120, 0xc0 }, ++ { 0xc121, 0x03 }, ++ { 0xe000, 0x88 }, ++ { 0xc321, 0x09 }, ++ { 0xc322, 0x01 }, ++ { 0xe706, 0x0f }, ++ { 0xe707, 0x30 }, ++ { 0xe806, 0x0f }, ++ { 0xe807, 0x30 }, ++ { 0xed00, 0xb0 }, ++ { 0xce04, 0x02 }, ++ { 0xce05, 0x63 }, ++ { 0xce06, 0x68 }, ++ { 0xce07, 0x07 }, ++ { 0xcf04, 0x02 }, ++ { 0xcf05, 0x63 }, ++ { 0xcf06, 0x68 }, ++ { 0xcf07, 0x07 }, ++ { 0xce60, 0xe3 }, ++ { 0xc130, 0x51 }, ++ { 0xf102, 0x00 }, ++ { 0xf103, 0x00 }, ++ { 0xf104, 0xf5 }, ++ { 0xf105, 0x06 }, ++ { 0xf109, 0x9b }, ++ { 0xf10a, 0x0b }, ++ { 0xf10b, 0x4c }, ++ { 0xf10b, 0x5c }, ++ { 0xf102, 0x00 }, ++ { 0xf103, 0x00 }, ++ { 0xf104, 0xf5 }, ++ { 0xf105, 0x0b }, ++ { 0xf109, 0x03 }, ++ { 0xf10a, 0x0b }, ++ { 0xf10b, 0x4c }, ++ { 0xf10b, 0x5c }, ++ { 0xf102, 0x00 }, ++ { 0xf103, 0x00 }, ++ { 0xf104, 0xf5 }, ++ { 0xf105, 0x0c }, ++ { 0xf109, 0x7f }, ++ { 0xf10a, 0x0b }, ++ { 0xf10b, 0x4c }, ++ { 0xf10b, 0x5c }, ++ ++ { 0xe604, 0x00 }, ++ { 0xdb00, 0x0c }, ++ { 0xdd00, 0x0c }, ++ { 0xdc19, 0x00 }, ++ { 0xdc1a, 0xff }, ++ { 0xdc1b, 0xff }, ++ { 0xdc1c, 0xff }, ++ { 0xdc1d, 0x00 }, ++ { 0xdc1e, 0x00 }, ++ { 0xdc1f, 0x00 }, ++ { 0xdc20, 0xff }, ++ { 0xde19, 0x00 }, ++ { 0xde1a, 0xff }, ++ { 0xde1b, 0xff }, ++ { 0xde1c, 0xff }, ++ { 0xde1d, 0x00 }, ++ { 0xde1e, 0x00 }, ++ { 0xde1f, 0x00 }, ++ { 0xde20, 0xff }, ++ { 0xdb32, 0x00 }, ++ { 0xdd32, 0x00 }, ++ { 0xdb33, 0x0a }, ++ { 0xdd33, 0x0a }, ++ { 0xdb34, 0x1a }, ++ { 0xdd34, 0x1a }, ++ { 0xdb17, 0xef }, ++ { 0xdd17, 0xef }, ++ { 0xdba7, 0x00 }, ++ { 0xdba8, 0x64 }, ++ { 0xdda7, 0x00 }, ++ { 0xdda8, 0x64 }, ++ { 0xdb19, 0x40 }, ++ { 0xdd19, 0x40 }, ++ { 0xdb00, 0x4c }, ++ { 0xdb01, 0x79 }, ++ { 0xdd01, 0x79 }, ++ { 0xdb04, 0x05 }, ++ { 0xdb05, 0x03 }, ++ { 0xdd04, 0x05 }, ++ { 0xdd05, 0x03 }, ++ { 0xdbbb, 0x09 }, ++ { 0xdbbc, 0x30 }, ++ { 0xdbbd, 0xf0 }, ++ { 0xdbbe, 0xf1 }, ++ { 0xddbb, 0x09 }, ++ { 0xddbc, 0x30 }, ++ { 0xddbd, 0xf0 }, ++ { 0xddbe, 0xf1 }, ++ { 0xdb01, 0x79 }, ++ { 0xdd01, 0x79 }, ++ { 0xdc52, 0xef }, ++ { 0xde52, 0xef }, ++ { 0x2f55, 0x22 }, ++}; ++ ++static const struct reg_default rt1318_reg_defaults[] = { ++ { 0x3000, 0x00 }, ++ { 0x3004, 0x01 }, ++ { 0x3005, 0x23 }, ++ { 0x3202, 0x00 }, ++ { 0x3203, 0x01 }, ++ { 0x3206, 0x00 }, ++ { 0xc000, 0x00 }, ++ { 0xc001, 0x43 }, ++ { 0xc003, 0x22 }, ++ { 0xc004, 0x44 }, ++ { 0xc005, 0x44 }, ++ { 0xc006, 0x33 }, ++ { 0xc007, 0x64 }, ++ { 0xc008, 0x05 }, ++ { 0xc00a, 0xfc }, ++ { 0xc00b, 0x0f }, ++ { 0xc00c, 0x0e }, ++ { 0xc00d, 0xef }, ++ { 0xc00e, 0xe5 }, ++ { 0xc00f, 0xff }, ++ { 0xc120, 0xc0 }, ++ { 0xc121, 0x00 }, ++ { 0xc122, 0x00 }, ++ { 0xc123, 0x14 }, ++ { 0xc125, 0x00 }, ++ { 0xc200, 0x00 }, ++ { 0xc201, 0x00 }, ++ { 0xc202, 0x00 }, ++ { 0xc203, 0x04 }, ++ { 0xc204, 0x00 }, ++ { 0xc205, 0x00 }, ++ { 0xc206, 0x68 }, ++ { 0xc207, 0x70 }, ++ { 0xc208, 0x00 }, ++ { 0xc20a, 0x00 }, ++ { 0xc20b, 0x01 }, ++ { 0xc20c, 0x7f }, ++ { 0xc20d, 0x01 }, ++ { 0xc20e, 0x7f }, ++ { 0xc300, 0x00 }, ++ { 0xc301, 0x00 }, ++ { 0xc303, 0x80 }, ++ { 0xc320, 0x00 }, ++ { 0xc321, 0x09 }, ++ { 0xc322, 0x02 }, ++ { 0xc410, 0x04 }, ++ { 0xc430, 0x00 }, ++ { 0xc431, 0x00 }, ++ { 0xca00, 0x10 }, ++ { 0xca01, 0x00 }, ++ { 0xca02, 0x0b }, ++ { 0xca10, 0x10 }, ++ { 0xca11, 0x00 }, ++ { 0xca12, 0x0b }, ++ { 0xdd93, 0x00 }, ++ { 0xdd94, 0x64 }, ++ { 0xe300, 0xa0 }, ++ { 0xed00, 0x80 }, ++ { 0xed01, 0x0f }, ++ { 0xed02, 0xff }, ++ { 0xed03, 0x00 }, ++ { 0xed04, 0x00 }, ++ { 0xed05, 0x0f }, ++ { 0xed06, 0xff }, ++ { 0xf010, 0x10 }, ++ { 0xf011, 0xec }, ++ { 0xf012, 0x68 }, ++ { 0xf013, 0x21 }, ++ { 0xf800, 0x00 }, ++ { 0xf801, 0x12 }, ++ { 0xf802, 0xe0 }, ++ { 0xf803, 0x2f }, ++ { 0xf804, 0x00 }, ++ { 0xf805, 0x00 }, ++ { 0xf806, 0x07 }, ++ { 0xf807, 0xff }, ++ { SDW_SDCA_CTL(FUNC_NUM_SMART_AMP, RT1318_SDCA_ENT_UDMPU21, RT1318_SDCA_CTL_UDMPU_CLUSTER, 0), 0x00 }, ++ { SDW_SDCA_CTL(FUNC_NUM_SMART_AMP, RT1318_SDCA_ENT_FU21, RT1318_SDCA_CTL_FU_MUTE, CH_L), 0x01 }, ++ { SDW_SDCA_CTL(FUNC_NUM_SMART_AMP, RT1318_SDCA_ENT_FU21, RT1318_SDCA_CTL_FU_MUTE, CH_R), 0x01 }, ++ { SDW_SDCA_CTL(FUNC_NUM_SMART_AMP, RT1318_SDCA_ENT_PDE23, RT1318_SDCA_CTL_REQ_POWER_STATE, 0), 0x03 }, ++ { SDW_SDCA_CTL(FUNC_NUM_SMART_AMP, RT1318_SDCA_ENT_CS21, RT1318_SDCA_CTL_SAMPLE_FREQ_INDEX, 0), 0x09 }, ++}; ++ ++static bool rt1318_readable_register(struct device *dev, unsigned int reg) ++{ ++ switch (reg) { ++ case 0x2f55: ++ case 0x3000: ++ case 0x3004 ... 0x3005: ++ case 0x3202 ... 0x3203: ++ case 0x3206: ++ case 0xc000 ... 0xc00f: ++ case 0xc120 ... 0xc125: ++ case 0xc200 ... 0xc20e: ++ case 0xc300 ... 0xc303: ++ case 0xc320 ... 0xc322: ++ case 0xc410: ++ case 0xc430 ... 0xc431: ++ case 0xca00 ... 0xca02: ++ case 0xca10 ... 0xca12: ++ case 0xcb00 ... 0xcb0b: ++ case 0xcc00 ... 0xcce5: ++ case 0xcd00 ... 0xcde5: ++ case 0xce00 ... 0xce6a: ++ case 0xcf00 ... 0xcf53: ++ case 0xd000 ... 0xd0cc: ++ case 0xd100 ... 0xd1b9: ++ case 0xdb00 ... 0xdc53: ++ case 0xdd00 ... 0xde53: ++ case 0xdf00 ... 0xdf6b: ++ case 0xe300: ++ case 0xeb00 ... 0xebcc: ++ case 0xec00 ... 0xecb9: ++ case 0xed00 ... 0xed06: ++ case 0xf010 ... 0xf014: ++ case 0xf800 ... 0xf807: ++ case SDW_SDCA_CTL(FUNC_NUM_SMART_AMP, RT1318_SDCA_ENT_UDMPU21, RT1318_SDCA_CTL_UDMPU_CLUSTER, 0): ++ case SDW_SDCA_CTL(FUNC_NUM_SMART_AMP, RT1318_SDCA_ENT_FU21, RT1318_SDCA_CTL_FU_MUTE, CH_L): ++ case SDW_SDCA_CTL(FUNC_NUM_SMART_AMP, RT1318_SDCA_ENT_FU21, RT1318_SDCA_CTL_FU_MUTE, CH_R): ++ case SDW_SDCA_CTL(FUNC_NUM_SMART_AMP, RT1318_SDCA_ENT_PDE23, RT1318_SDCA_CTL_REQ_POWER_STATE, 0): ++ case SDW_SDCA_CTL(FUNC_NUM_SMART_AMP, RT1318_SDCA_ENT_CS21, RT1318_SDCA_CTL_SAMPLE_FREQ_INDEX, 0): ++ case SDW_SDCA_CTL(FUNC_NUM_SMART_AMP, RT1318_SDCA_ENT_SAPU, RT1318_SDCA_CTL_SAPU_PROTECTION_MODE, 0): ++ case SDW_SDCA_CTL(FUNC_NUM_SMART_AMP, RT1318_SDCA_ENT_SAPU, RT1318_SDCA_CTL_SAPU_PROTECTION_STATUS, 0): ++ return true; ++ default: ++ return false; ++ } ++} ++ ++static bool rt1318_volatile_register(struct device *dev, unsigned int reg) ++{ ++ switch (reg) { ++ case 0x2f55: ++ case 0x3000 ... 0x3001: ++ case 0xc000: ++ case 0xc301: ++ case 0xc410: ++ case 0xc430 ... 0xc431: ++ case 0xdb06: ++ case 0xdb12: ++ case 0xdb1d ... 0xdb1f: ++ case 0xdb35: ++ case 0xdb37: ++ case 0xdb8a ... 0xdb92: ++ case 0xdbc5 ... 0xdbc8: ++ case 0xdc2b ... 0xdc49: ++ case 0xdd0b: ++ case 0xdd12: ++ case 0xdd1d ... 0xdd1f: ++ case 0xdd35: ++ case 0xdd8a ... 0xdd92: ++ case 0xddc5 ... 0xddc8: ++ case 0xde2b ... 0xde44: ++ case 0xdf4a ... 0xdf55: ++ case 0xe224 ... 0xe23b: ++ case 0xea01: ++ case 0xebc5: ++ case 0xebc8: ++ case 0xebcb ... 0xebcc: ++ case 0xed03 ... 0xed06: ++ case 0xf010 ... 0xf014: ++ case SDW_SDCA_CTL(FUNC_NUM_SMART_AMP, RT1318_SDCA_ENT_SAPU, RT1318_SDCA_CTL_SAPU_PROTECTION_MODE, 0): ++ case SDW_SDCA_CTL(FUNC_NUM_SMART_AMP, RT1318_SDCA_ENT_SAPU, RT1318_SDCA_CTL_SAPU_PROTECTION_STATUS, 0): ++ return true; ++ default: ++ return false; ++ } ++} ++ ++static const struct regmap_config rt1318_sdw_regmap = { ++ .reg_bits = 32, ++ .val_bits = 8, ++ .readable_reg = rt1318_readable_register, ++ .volatile_reg = rt1318_volatile_register, ++ .max_register = 0x41081488, ++ .reg_defaults = rt1318_reg_defaults, ++ .num_reg_defaults = ARRAY_SIZE(rt1318_reg_defaults), ++ .cache_type = REGCACHE_RBTREE, ++ .use_single_read = true, ++ .use_single_write = true, ++}; ++ ++static int rt1318_read_prop(struct sdw_slave *slave) ++{ ++ struct sdw_slave_prop *prop = &slave->prop; ++ int nval; ++ int i, j; ++ u32 bit; ++ unsigned long addr; ++ struct sdw_dpn_prop *dpn; ++ ++ prop->scp_int1_mask = SDW_SCP_INT1_BUS_CLASH | SDW_SCP_INT1_PARITY; ++ prop->quirks = SDW_SLAVE_QUIRKS_INVALID_INITIAL_PARITY; ++ prop->is_sdca = true; ++ ++ prop->paging_support = true; ++ ++ /* first we need to allocate memory for set bits in port lists */ ++ prop->source_ports = BIT(2); ++ prop->sink_ports = BIT(1); ++ ++ nval = hweight32(prop->source_ports); ++ prop->src_dpn_prop = devm_kcalloc(&slave->dev, nval, ++ sizeof(*prop->src_dpn_prop), GFP_KERNEL); ++ if (!prop->src_dpn_prop) ++ return -ENOMEM; ++ ++ i = 0; ++ dpn = prop->src_dpn_prop; ++ addr = prop->source_ports; ++ for_each_set_bit(bit, &addr, 32) { ++ dpn[i].num = bit; ++ dpn[i].type = SDW_DPN_FULL; ++ dpn[i].simple_ch_prep_sm = true; ++ dpn[i].ch_prep_timeout = 10; ++ i++; ++ } ++ ++ /* do this again for sink now */ ++ nval = hweight32(prop->sink_ports); ++ prop->sink_dpn_prop = devm_kcalloc(&slave->dev, nval, ++ sizeof(*prop->sink_dpn_prop), GFP_KERNEL); ++ if (!prop->sink_dpn_prop) ++ return -ENOMEM; ++ ++ j = 0; ++ dpn = prop->sink_dpn_prop; ++ addr = prop->sink_ports; ++ for_each_set_bit(bit, &addr, 32) { ++ dpn[j].num = bit; ++ dpn[j].type = SDW_DPN_FULL; ++ dpn[j].simple_ch_prep_sm = true; ++ dpn[j].ch_prep_timeout = 10; ++ j++; ++ } ++ ++ /* set the timeout values */ ++ prop->clk_stop_timeout = 20; ++ ++ return 0; ++} ++ ++static int rt1318_io_init(struct device *dev, struct sdw_slave *slave) ++{ ++ struct rt1318_sdw_priv *rt1318 = dev_get_drvdata(dev); ++ ++ if (rt1318->hw_init) ++ return 0; ++ ++ if (rt1318->first_hw_init) { ++ regcache_cache_only(rt1318->regmap, false); ++ regcache_cache_bypass(rt1318->regmap, true); ++ } else { ++ /* ++ * PM runtime is only enabled when a Slave reports as Attached ++ */ ++ ++ /* set autosuspend parameters */ ++ pm_runtime_set_autosuspend_delay(&slave->dev, 3000); ++ pm_runtime_use_autosuspend(&slave->dev); ++ ++ /* update count of parent 'active' children */ ++ pm_runtime_set_active(&slave->dev); ++ ++ /* make sure the device does not suspend immediately */ ++ pm_runtime_mark_last_busy(&slave->dev); ++ ++ pm_runtime_enable(&slave->dev); ++ } ++ ++ pm_runtime_get_noresume(&slave->dev); ++ ++ /* blind write */ ++ regmap_multi_reg_write(rt1318->regmap, rt1318_blind_write, ++ ARRAY_SIZE(rt1318_blind_write)); ++ ++ if (rt1318->first_hw_init) { ++ regcache_cache_bypass(rt1318->regmap, false); ++ regcache_mark_dirty(rt1318->regmap); ++ } ++ ++ /* Mark Slave initialization complete */ ++ rt1318->first_hw_init = true; ++ rt1318->hw_init = true; ++ ++ pm_runtime_mark_last_busy(&slave->dev); ++ pm_runtime_put_autosuspend(&slave->dev); ++ ++ dev_dbg(&slave->dev, "%s hw_init complete\n", __func__); ++ return 0; ++} ++ ++static int rt1318_update_status(struct sdw_slave *slave, ++ enum sdw_slave_status status) ++{ ++ struct rt1318_sdw_priv *rt1318 = dev_get_drvdata(&slave->dev); ++ ++ /* Update the status */ ++ rt1318->status = status; ++ ++ if (status == SDW_SLAVE_UNATTACHED) ++ rt1318->hw_init = false; ++ ++ /* ++ * Perform initialization only if slave status is present and ++ * hw_init flag is false ++ */ ++ if (rt1318->hw_init || rt1318->status != SDW_SLAVE_ATTACHED) ++ return 0; ++ ++ /* perform I/O transfers required for Slave initialization */ ++ return rt1318_io_init(&slave->dev, slave); ++} ++ ++static int rt1318_classd_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 rt1318_sdw_priv *rt1318 = snd_soc_component_get_drvdata(component); ++ unsigned char ps0 = 0x0, ps3 = 0x3; ++ ++ switch (event) { ++ case SND_SOC_DAPM_POST_PMU: ++ regmap_write(rt1318->regmap, ++ SDW_SDCA_CTL(FUNC_NUM_SMART_AMP, RT1318_SDCA_ENT_PDE23, ++ RT1318_SDCA_CTL_REQ_POWER_STATE, 0), ++ ps0); ++ break; ++ case SND_SOC_DAPM_PRE_PMD: ++ regmap_write(rt1318->regmap, ++ SDW_SDCA_CTL(FUNC_NUM_SMART_AMP, RT1318_SDCA_ENT_PDE23, ++ RT1318_SDCA_CTL_REQ_POWER_STATE, 0), ++ ps3); ++ break; ++ ++ default: ++ break; ++ } ++ ++ return 0; ++} ++ ++static const char * const rt1318_rx_data_ch_select[] = { ++ "L,R", ++ "L,L", ++ "L,R", ++ "L,L+R", ++ "R,L", ++ "R,R", ++ "R,L+R", ++ "L+R,L", ++ "L+R,R", ++ "L+R,L+R", ++}; ++ ++static SOC_ENUM_SINGLE_DECL(rt1318_rx_data_ch_enum, ++ SDW_SDCA_CTL(FUNC_NUM_SMART_AMP, RT1318_SDCA_ENT_UDMPU21, RT1318_SDCA_CTL_UDMPU_CLUSTER, 0), 0, ++ rt1318_rx_data_ch_select); ++ ++static const struct snd_kcontrol_new rt1318_snd_controls[] = { ++ ++ /* UDMPU Cluster Selection */ ++ SOC_ENUM("RX Channel Select", rt1318_rx_data_ch_enum), ++}; ++ ++static const struct snd_kcontrol_new rt1318_sto_dac = ++ SOC_DAPM_DOUBLE_R("Switch", ++ SDW_SDCA_CTL(FUNC_NUM_SMART_AMP, RT1318_SDCA_ENT_FU21, RT1318_SDCA_CTL_FU_MUTE, CH_L), ++ SDW_SDCA_CTL(FUNC_NUM_SMART_AMP, RT1318_SDCA_ENT_FU21, RT1318_SDCA_CTL_FU_MUTE, CH_R), ++ 0, 1, 1); ++ ++static const struct snd_soc_dapm_widget rt1318_dapm_widgets[] = { ++ /* Audio Interface */ ++ SND_SOC_DAPM_AIF_IN("DP1RX", "DP1 Playback", 0, SND_SOC_NOPM, 0, 0), ++ SND_SOC_DAPM_AIF_OUT("DP2TX", "DP2 Capture", 0, SND_SOC_NOPM, 0, 0), ++ ++ /* Digital Interface */ ++ SND_SOC_DAPM_SWITCH("DAC", SND_SOC_NOPM, 0, 0, &rt1318_sto_dac), ++ ++ /* Output */ ++ SND_SOC_DAPM_PGA_E("CLASS D", SND_SOC_NOPM, 0, 0, NULL, 0, ++ rt1318_classd_event, SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), ++ SND_SOC_DAPM_OUTPUT("SPOL"), ++ SND_SOC_DAPM_OUTPUT("SPOR"), ++ /* Input */ ++ SND_SOC_DAPM_PGA("FB Data", SND_SOC_NOPM, 0, 0, NULL, 0), ++ SND_SOC_DAPM_SIGGEN("FB Gen"), ++}; ++ ++static const struct snd_soc_dapm_route rt1318_dapm_routes[] = { ++ { "DAC", "Switch", "DP1RX" }, ++ { "CLASS D", NULL, "DAC" }, ++ { "SPOL", NULL, "CLASS D" }, ++ { "SPOR", NULL, "CLASS D" }, ++ ++ { "FB Data", NULL, "FB Gen" }, ++ { "DP2TX", NULL, "FB Data" }, ++}; ++ ++static int rt1318_set_sdw_stream(struct snd_soc_dai *dai, void *sdw_stream, ++ int direction) ++{ ++ struct sdw_stream_data *stream; ++ ++ if (!sdw_stream) ++ return 0; ++ ++ stream = kzalloc(sizeof(*stream), GFP_KERNEL); ++ if (!stream) ++ return -ENOMEM; ++ ++ stream->sdw_stream = sdw_stream; ++ ++ /* Use tx_mask or rx_mask to configure stream tag and set dma_data */ ++ if (direction == SNDRV_PCM_STREAM_PLAYBACK) ++ dai->playback_dma_data = stream; ++ else ++ dai->capture_dma_data = stream; ++ ++ return 0; ++} ++ ++static void rt1318_sdw_shutdown(struct snd_pcm_substream *substream, ++ struct snd_soc_dai *dai) ++{ ++ struct sdw_stream_data *stream; ++ ++ stream = snd_soc_dai_get_dma_data(dai, substream); ++ snd_soc_dai_set_dma_data(dai, substream, NULL); ++ kfree(stream); ++} ++ ++static int rt1318_sdw_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; ++ struct rt1318_sdw_priv *rt1318 = ++ snd_soc_component_get_drvdata(component); ++ struct sdw_stream_config stream_config; ++ struct sdw_port_config port_config; ++ enum sdw_data_direction direction; ++ struct sdw_stream_data *stream; ++ int retval, port, num_channels, ch_mask; ++ unsigned int sampling_rate; ++ ++ dev_dbg(dai->dev, "%s %s", __func__, dai->name); ++ stream = snd_soc_dai_get_dma_data(dai, substream); ++ ++ if (!stream) ++ return -EINVAL; ++ ++ if (!rt1318->sdw_slave) ++ return -EINVAL; ++ ++ /* SoundWire specific configuration */ ++ /* port 1 for playback */ ++ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { ++ direction = SDW_DATA_DIR_RX; ++ port = 1; ++ } else { ++ direction = SDW_DATA_DIR_TX; ++ port = 2; ++ } ++ ++ num_channels = params_channels(params); ++ ch_mask = (1 << num_channels) - 1; ++ ++ stream_config.frame_rate = params_rate(params); ++ stream_config.ch_count = num_channels; ++ stream_config.bps = snd_pcm_format_width(params_format(params)); ++ stream_config.direction = direction; ++ ++ port_config.ch_mask = ch_mask; ++ port_config.num = port; ++ ++ retval = sdw_stream_add_slave(rt1318->sdw_slave, &stream_config, ++ &port_config, 1, stream->sdw_stream); ++ if (retval) { ++ dev_err(dai->dev, "Unable to configure port\n"); ++ return retval; ++ } ++ ++ /* sampling rate configuration */ ++ switch (params_rate(params)) { ++ case 16000: ++ sampling_rate = RT1318_SDCA_RATE_16000HZ; ++ break; ++ case 32000: ++ sampling_rate = RT1318_SDCA_RATE_32000HZ; ++ break; ++ case 44100: ++ sampling_rate = RT1318_SDCA_RATE_44100HZ; ++ break; ++ case 48000: ++ sampling_rate = RT1318_SDCA_RATE_48000HZ; ++ break; ++ case 96000: ++ sampling_rate = RT1318_SDCA_RATE_96000HZ; ++ break; ++ case 192000: ++ sampling_rate = RT1318_SDCA_RATE_192000HZ; ++ break; ++ default: ++ dev_err(component->dev, "Rate %d is not supported\n", ++ params_rate(params)); ++ return -EINVAL; ++ } ++ ++ /* set sampling frequency */ ++ regmap_write(rt1318->regmap, ++ SDW_SDCA_CTL(FUNC_NUM_SMART_AMP, RT1318_SDCA_ENT_CS21, RT1318_SDCA_CTL_SAMPLE_FREQ_INDEX, 0), ++ sampling_rate); ++ ++ return 0; ++} ++ ++static int rt1318_sdw_pcm_hw_free(struct snd_pcm_substream *substream, ++ struct snd_soc_dai *dai) ++{ ++ struct snd_soc_component *component = dai->component; ++ struct rt1318_sdw_priv *rt1318 = ++ snd_soc_component_get_drvdata(component); ++ struct sdw_stream_data *stream = ++ snd_soc_dai_get_dma_data(dai, substream); ++ ++ if (!rt1318->sdw_slave) ++ return -EINVAL; ++ ++ sdw_stream_remove_slave(rt1318->sdw_slave, stream->sdw_stream); ++ return 0; ++} ++ ++/* ++ * slave_ops: callbacks for get_clock_stop_mode, clock_stop and ++ * port_prep are not defined for now ++ */ ++static struct sdw_slave_ops rt1318_slave_ops = { ++ .read_prop = rt1318_read_prop, ++ .update_status = rt1318_update_status, ++}; ++ ++static int rt1318_sdw_component_probe(struct snd_soc_component *component) ++{ ++ int ret; ++ struct rt1318_sdw_priv *rt1318 = snd_soc_component_get_drvdata(component); ++ ++ rt1318->component = component; ++ ++ ret = pm_runtime_resume(component->dev); ++ dev_dbg(&rt1318->sdw_slave->dev, "%s pm_runtime_resume, ret=%d", __func__, ret); ++ if (ret < 0 && ret != -EACCES) ++ return ret; ++ ++ return 0; ++} ++ ++static const struct snd_soc_component_driver soc_component_sdw_rt1318 = { ++ .probe = rt1318_sdw_component_probe, ++ .controls = rt1318_snd_controls, ++ .num_controls = ARRAY_SIZE(rt1318_snd_controls), ++ .dapm_widgets = rt1318_dapm_widgets, ++ .num_dapm_widgets = ARRAY_SIZE(rt1318_dapm_widgets), ++ .dapm_routes = rt1318_dapm_routes, ++ .num_dapm_routes = ARRAY_SIZE(rt1318_dapm_routes), ++ .endianness = 1, ++}; ++ ++static const struct snd_soc_dai_ops rt1318_aif_dai_ops = { ++ .hw_params = rt1318_sdw_hw_params, ++ .hw_free = rt1318_sdw_pcm_hw_free, ++ .set_stream = rt1318_set_sdw_stream, ++ .shutdown = rt1318_sdw_shutdown, ++}; ++ ++#define RT1318_STEREO_RATES (SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \ ++ SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_192000) ++#define RT1318_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE | \ ++ SNDRV_PCM_FMTBIT_S32_LE) ++ ++static struct snd_soc_dai_driver rt1318_sdw_dai[] = { ++ { ++ .name = "rt1318-aif", ++ .playback = { ++ .stream_name = "DP1 Playback", ++ .channels_min = 1, ++ .channels_max = 2, ++ .rates = RT1318_STEREO_RATES, ++ .formats = RT1318_FORMATS, ++ }, ++ .capture = { ++ .stream_name = "DP2 Capture", ++ .channels_min = 1, ++ .channels_max = 2, ++ .rates = RT1318_STEREO_RATES, ++ .formats = RT1318_FORMATS, ++ }, ++ .ops = &rt1318_aif_dai_ops, ++ }, ++}; ++ ++static int rt1318_sdw_init(struct device *dev, struct regmap *regmap, ++ struct sdw_slave *slave) ++{ ++ struct rt1318_sdw_priv *rt1318; ++ int ret; ++ ++ rt1318 = devm_kzalloc(dev, sizeof(*rt1318), GFP_KERNEL); ++ if (!rt1318) ++ return -ENOMEM; ++ ++ dev_set_drvdata(dev, rt1318); ++ rt1318->sdw_slave = slave; ++ rt1318->regmap = regmap; ++ ++ /* ++ * Mark hw_init to false ++ * HW init will be performed when device reports present ++ */ ++ rt1318->hw_init = false; ++ rt1318->first_hw_init = false; ++ ++ ret = devm_snd_soc_register_component(dev, ++ &soc_component_sdw_rt1318, ++ rt1318_sdw_dai, ++ ARRAY_SIZE(rt1318_sdw_dai)); ++ ++ dev_dbg(&slave->dev, "%s\n", __func__); ++ ++ return ret; ++} ++ ++static int rt1318_sdw_probe(struct sdw_slave *slave, ++ const struct sdw_device_id *id) ++{ ++ struct regmap *regmap; ++ ++ /* Regmap Initialization */ ++ regmap = devm_regmap_init_sdw(slave, &rt1318_sdw_regmap); ++ if (IS_ERR(regmap)) ++ return PTR_ERR(regmap); ++ ++ return rt1318_sdw_init(&slave->dev, regmap, slave); ++} ++ ++static int rt1318_sdw_remove(struct sdw_slave *slave) ++{ ++ struct rt1318_sdw_priv *rt1318 = dev_get_drvdata(&slave->dev); ++ ++ if (rt1318->first_hw_init) ++ pm_runtime_disable(&slave->dev); ++ ++ return 0; ++} ++ ++static const struct sdw_device_id rt1318_id[] = { ++ SDW_SLAVE_ENTRY_EXT(0x025d, 0x1318, 0x3, 0x1, 0), ++ {}, ++}; ++MODULE_DEVICE_TABLE(sdw, rt1318_id); ++ ++static int __maybe_unused rt1318_dev_suspend(struct device *dev) ++{ ++ struct rt1318_sdw_priv *rt1318 = dev_get_drvdata(dev); ++ ++ if (!rt1318->hw_init) ++ return 0; ++ ++ regcache_cache_only(rt1318->regmap, true); ++ return 0; ++} ++ ++#define RT1318_PROBE_TIMEOUT 5000 ++ ++static int __maybe_unused rt1318_dev_resume(struct device *dev) ++{ ++ struct sdw_slave *slave = dev_to_sdw_dev(dev); ++ struct rt1318_sdw_priv *rt1318 = dev_get_drvdata(dev); ++ unsigned long time; ++ ++ if (!rt1318->first_hw_init) ++ return 0; ++ ++ if (!slave->unattach_request) ++ goto regmap_sync; ++ ++ time = wait_for_completion_timeout(&slave->initialization_complete, ++ msecs_to_jiffies(RT1318_PROBE_TIMEOUT)); ++ if (!time) { ++ dev_err(&slave->dev, "Initialization not complete, timed out\n"); ++ return -ETIMEDOUT; ++ } ++ ++regmap_sync: ++ slave->unattach_request = 0; ++ regcache_cache_only(rt1318->regmap, false); ++ regcache_sync(rt1318->regmap); ++ ++ return 0; ++} ++ ++static const struct dev_pm_ops rt1318_pm = { ++ SET_SYSTEM_SLEEP_PM_OPS(rt1318_dev_suspend, rt1318_dev_resume) ++ SET_RUNTIME_PM_OPS(rt1318_dev_suspend, rt1318_dev_resume, NULL) ++}; ++ ++static struct sdw_driver rt1318_sdw_driver = { ++ .driver = { ++ .name = "rt1318-sdca", ++ .owner = THIS_MODULE, ++ .pm = &rt1318_pm, ++ }, ++ .probe = rt1318_sdw_probe, ++ .remove = rt1318_sdw_remove, ++ .ops = &rt1318_slave_ops, ++ .id_table = rt1318_id, ++}; ++module_sdw_driver(rt1318_sdw_driver); ++ ++MODULE_DESCRIPTION("ASoC RT1318 driver SDCA SDW"); ++MODULE_AUTHOR("Shuming Fan "); ++MODULE_LICENSE("GPL"); +diff --git a/sound/soc/codecs/rt1318-sdw.h b/sound/soc/codecs/rt1318-sdw.h +new file mode 100644 +index 0000000000000..4d7ac9c4bd8de +--- /dev/null ++++ b/sound/soc/codecs/rt1318-sdw.h +@@ -0,0 +1,101 @@ ++/* SPDX-License-Identifier: GPL-2.0-only */ ++/* ++ * rt1318-sdw.h -- RT1318 SDCA ALSA SoC audio driver header ++ * ++ * Copyright(c) 2022 Realtek Semiconductor Corp. ++ */ ++ ++#ifndef __RT1318_SDW_H__ ++#define __RT1318_SDW_H__ ++ ++#include ++#include ++#include ++#include ++#include ++ ++/* imp-defined registers */ ++#define RT1318_SAPU_SM 0x3203 ++ ++#define R1318_TCON 0xc203 ++#define R1318_TCON_RELATED_1 0xc206 ++ ++#define R1318_SPK_TEMPERATRUE_PROTECTION_0 0xdb00 ++#define R1318_SPK_TEMPERATRUE_PROTECTION_L_4 0xdb08 ++#define R1318_SPK_TEMPERATRUE_PROTECTION_R_4 0xdd08 ++ ++#define R1318_SPK_TEMPERATRUE_PROTECTION_L_6 0xdb12 ++#define R1318_SPK_TEMPERATRUE_PROTECTION_R_6 0xdd12 ++ ++#define RT1318_INIT_RECIPROCAL_REG_L_24 0xdbb5 ++#define RT1318_INIT_RECIPROCAL_REG_L_23_16 0xdbb6 ++#define RT1318_INIT_RECIPROCAL_REG_L_15_8 0xdbb7 ++#define RT1318_INIT_RECIPROCAL_REG_L_7_0 0xdbb8 ++#define RT1318_INIT_RECIPROCAL_REG_R_24 0xddb5 ++#define RT1318_INIT_RECIPROCAL_REG_R_23_16 0xddb6 ++#define RT1318_INIT_RECIPROCAL_REG_R_15_8 0xddb7 ++#define RT1318_INIT_RECIPROCAL_REG_R_7_0 0xddb8 ++ ++#define RT1318_INIT_R0_RECIPROCAL_SYN_L_24 0xdbc5 ++#define RT1318_INIT_R0_RECIPROCAL_SYN_L_23_16 0xdbc6 ++#define RT1318_INIT_R0_RECIPROCAL_SYN_L_15_8 0xdbc7 ++#define RT1318_INIT_R0_RECIPROCAL_SYN_L_7_0 0xdbc8 ++#define RT1318_INIT_R0_RECIPROCAL_SYN_R_24 0xddc5 ++#define RT1318_INIT_R0_RECIPROCAL_SYN_R_23_16 0xddc6 ++#define RT1318_INIT_R0_RECIPROCAL_SYN_R_15_8 0xddc7 ++#define RT1318_INIT_R0_RECIPROCAL_SYN_R_7_0 0xddc8 ++ ++#define RT1318_R0_COMPARE_FLAG_L 0xdb35 ++#define RT1318_R0_COMPARE_FLAG_R 0xdd35 ++ ++#define RT1318_STP_INITIAL_RS_TEMP_H 0xdd93 ++#define RT1318_STP_INITIAL_RS_TEMP_L 0xdd94 ++ ++/* RT1318 SDCA Control - function number */ ++#define FUNC_NUM_SMART_AMP 0x04 ++ ++/* RT1318 SDCA entity */ ++#define RT1318_SDCA_ENT_PDE23 0x31 ++#define RT1318_SDCA_ENT_XU24 0x24 ++#define RT1318_SDCA_ENT_FU21 0x03 ++#define RT1318_SDCA_ENT_UDMPU21 0x02 ++#define RT1318_SDCA_ENT_CS21 0x21 ++#define RT1318_SDCA_ENT_SAPU 0x29 ++ ++/* RT1318 SDCA control */ ++#define RT1318_SDCA_CTL_SAMPLE_FREQ_INDEX 0x10 ++#define RT1318_SDCA_CTL_REQ_POWER_STATE 0x01 ++#define RT1318_SDCA_CTL_FU_MUTE 0x01 ++#define RT1318_SDCA_CTL_FU_VOLUME 0x02 ++#define RT1318_SDCA_CTL_UDMPU_CLUSTER 0x10 ++#define RT1318_SDCA_CTL_SAPU_PROTECTION_MODE 0x10 ++#define RT1318_SDCA_CTL_SAPU_PROTECTION_STATUS 0x11 ++ ++/* RT1318 SDCA channel */ ++#define CH_L 0x01 ++#define CH_R 0x02 ++ ++/* sample frequency index */ ++#define RT1318_SDCA_RATE_16000HZ 0x04 ++#define RT1318_SDCA_RATE_32000HZ 0x07 ++#define RT1318_SDCA_RATE_44100HZ 0x08 ++#define RT1318_SDCA_RATE_48000HZ 0x09 ++#define RT1318_SDCA_RATE_96000HZ 0x0b ++#define RT1318_SDCA_RATE_192000HZ 0x0d ++ ++ ++struct rt1318_sdw_priv { ++ struct snd_soc_component *component; ++ struct regmap *regmap; ++ struct sdw_slave *sdw_slave; ++ enum sdw_slave_status status; ++ struct sdw_bus_params params; ++ bool hw_init; ++ bool first_hw_init; ++}; ++ ++struct sdw_stream_data { ++ struct sdw_stream_runtime *sdw_stream; ++}; ++ ++#endif /* __RT1318_SDW_H__ */ +-- +2.42.0 + diff --git a/queue-5.15/asoc-rt9120-add-rt9210-audio-amplifier-support.patch b/queue-5.15/asoc-rt9120-add-rt9210-audio-amplifier-support.patch new file mode 100644 index 00000000000..366a8596baa --- /dev/null +++ b/queue-5.15/asoc-rt9120-add-rt9210-audio-amplifier-support.patch @@ -0,0 +1,570 @@ +From 3eb856ca929d5861d87aaf04ee7384adea72a3d5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 8 Oct 2021 12:50:12 +0800 +Subject: ASoC: rt9120: Add rt9210 audio amplifier support + +From: ChiYuan Huang + +[ Upstream commit f218b5e2662c261c6acce5036ad4067669e51eac ] + +Add Richtek rt9120 audio amplifier support. + +Signed-off-by: ChiYuan Huang +[Fix a Gain->Volume -- broonie] +Message-Id: <1633668612-25524-3-git-send-email-u0084500@gmail.com> +Signed-off-by: Mark Brown +Stable-dep-of: da29b94ed354 ("ASoC: codecs: wcd938x: fix resource leaks on bind errors") +Signed-off-by: Sasha Levin +--- + sound/soc/codecs/Kconfig | 10 + + sound/soc/codecs/Makefile | 2 + + sound/soc/codecs/rt9120.c | 489 ++++++++++++++++++++++++++++++++++++++ + 3 files changed, 501 insertions(+) + create mode 100644 sound/soc/codecs/rt9120.c + +diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig +index 1750cc888bbe8..b193db25c37fe 100644 +--- a/sound/soc/codecs/Kconfig ++++ b/sound/soc/codecs/Kconfig +@@ -187,6 +187,7 @@ config SND_SOC_ALL_CODECS + imply SND_SOC_RT715_SDCA_SDW + imply SND_SOC_RT1308_SDW + imply SND_SOC_RT1316_SDW ++ imply SND_SOC_RT9120 + imply SND_SOC_SDW_MOCKUP + imply SND_SOC_SGTL5000 + imply SND_SOC_SI476X +@@ -1290,6 +1291,15 @@ config SND_SOC_RT715_SDCA_SDW + select REGMAP_SOUNDWIRE + select REGMAP_SOUNDWIRE_MBQ + ++config SND_SOC_RT9120 ++ tristate "Richtek RT9120 Stereo Class-D Amplifier" ++ depends on I2C ++ select REGMAP_I2C ++ select GPIOLIB ++ help ++ Enable support for Richtek RT9120 20W, stereo, inductor-less, ++ high-efficiency Class-D audio amplifier. ++ + config SND_SOC_SDW_MOCKUP + tristate "SoundWire mockup codec" + depends on EXPERT +diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile +index 8dcea2c4604aa..5ba164d41b300 100644 +--- a/sound/soc/codecs/Makefile ++++ b/sound/soc/codecs/Makefile +@@ -203,6 +203,7 @@ snd-soc-rt711-objs := rt711.o rt711-sdw.o + snd-soc-rt711-sdca-objs := rt711-sdca.o rt711-sdca-sdw.o + snd-soc-rt715-objs := rt715.o rt715-sdw.o + snd-soc-rt715-sdca-objs := rt715-sdca.o rt715-sdca-sdw.o ++snd-soc-rt9120-objs := rt9120.o + snd-soc-sdw-mockup-objs := sdw-mockup.o + snd-soc-sgtl5000-objs := sgtl5000.o + snd-soc-alc5623-objs := alc5623.o +@@ -531,6 +532,7 @@ obj-$(CONFIG_SND_SOC_RT711) += snd-soc-rt711.o + obj-$(CONFIG_SND_SOC_RT711_SDCA_SDW) += snd-soc-rt711-sdca.o + obj-$(CONFIG_SND_SOC_RT715) += snd-soc-rt715.o + obj-$(CONFIG_SND_SOC_RT715_SDCA_SDW) += snd-soc-rt715-sdca.o ++obj-$(CONFIG_SND_SOC_RT9120) += snd-soc-rt9120.o + obj-$(CONFIG_SND_SOC_SDW_MOCKUP) += snd-soc-sdw-mockup.o + obj-$(CONFIG_SND_SOC_SGTL5000) += snd-soc-sgtl5000.o + obj-$(CONFIG_SND_SOC_SIGMADSP) += snd-soc-sigmadsp.o +diff --git a/sound/soc/codecs/rt9120.c b/sound/soc/codecs/rt9120.c +new file mode 100644 +index 0000000000000..2c95178f4ff84 +--- /dev/null ++++ b/sound/soc/codecs/rt9120.c +@@ -0,0 +1,489 @@ ++// SPDX-License-Identifier: GPL-2.0 ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define RT9120_REG_DEVID 0x00 ++#define RT9120_REG_I2SFMT 0x02 ++#define RT9120_REG_I2SWL 0x03 ++#define RT9120_REG_SDIOSEL 0x04 ++#define RT9120_REG_SYSCTL 0x05 ++#define RT9120_REG_SPKGAIN 0x07 ++#define RT9120_REG_VOLRAMP 0x0A ++#define RT9120_REG_ERRRPT 0x10 ++#define RT9120_REG_MSVOL 0x20 ++#define RT9120_REG_SWRESET 0x40 ++#define RT9120_REG_INTERNAL0 0x65 ++#define RT9120_REG_INTERNAL1 0x69 ++#define RT9120_REG_UVPOPT 0x6C ++ ++#define RT9120_VID_MASK GENMASK(15, 8) ++#define RT9120_SWRST_MASK BIT(7) ++#define RT9120_MUTE_MASK GENMASK(5, 4) ++#define RT9120_I2SFMT_MASK GENMASK(4, 2) ++#define RT9120_I2SFMT_SHIFT 2 ++#define RT9120_CFG_FMT_I2S 0 ++#define RT9120_CFG_FMT_LEFTJ 1 ++#define RT9120_CFG_FMT_RIGHTJ 2 ++#define RT9120_CFG_FMT_DSPA 3 ++#define RT9120_CFG_FMT_DSPB 7 ++#define RT9120_AUDBIT_MASK GENMASK(1, 0) ++#define RT9120_CFG_AUDBIT_16 0 ++#define RT9120_CFG_AUDBIT_20 1 ++#define RT9120_CFG_AUDBIT_24 2 ++#define RT9120_AUDWL_MASK GENMASK(5, 0) ++#define RT9120_CFG_WORDLEN_16 16 ++#define RT9120_CFG_WORDLEN_24 24 ++#define RT9120_CFG_WORDLEN_32 32 ++#define RT9120_DVDD_UVSEL_MASK GENMASK(5, 4) ++ ++#define RT9120_VENDOR_ID 0x4200 ++#define RT9120_RESET_WAITMS 20 ++#define RT9120_CHIPON_WAITMS 20 ++#define RT9120_AMPON_WAITMS 50 ++#define RT9120_AMPOFF_WAITMS 100 ++#define RT9120_LVAPP_THRESUV 2000000 ++ ++/* 8000 to 192000 supported , only 176400 not support */ ++#define RT9120_RATES_MASK (SNDRV_PCM_RATE_8000_192000 &\ ++ ~SNDRV_PCM_RATE_176400) ++#define RT9120_FMTS_MASK (SNDRV_PCM_FMTBIT_S16_LE |\ ++ SNDRV_PCM_FMTBIT_S24_LE |\ ++ SNDRV_PCM_FMTBIT_S32_LE) ++ ++struct rt9120_data { ++ struct device *dev; ++ struct regmap *regmap; ++}; ++ ++/* 11bit [min,max,step] = [-103.9375dB, 24dB, 0.0625dB] */ ++static const DECLARE_TLV_DB_SCALE(digital_gain, -1039375, 625, -1039375); ++ ++static const char * const sdo_select_text[] = { ++ "None", "INTF", "Final", "RMS Detect" ++}; ++ ++static const struct soc_enum sdo_select_enum = ++ SOC_ENUM_SINGLE(RT9120_REG_SDIOSEL, 4, ARRAY_SIZE(sdo_select_text), ++ sdo_select_text); ++ ++static const struct snd_kcontrol_new rt9120_snd_controls[] = { ++ SOC_SINGLE_TLV("MS Volume", RT9120_REG_MSVOL, 0, 2047, 1, digital_gain), ++ SOC_SINGLE("SPK Volume", RT9120_REG_SPKGAIN, 0, 7, 0), ++ SOC_SINGLE("PBTL Switch", RT9120_REG_SYSCTL, 3, 1, 0), ++ SOC_ENUM("SDO Select", sdo_select_enum), ++}; ++ ++static int internal_power_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); ++ ++ switch (event) { ++ case SND_SOC_DAPM_PRE_PMU: ++ snd_soc_component_write(comp, RT9120_REG_ERRRPT, 0); ++ break; ++ case SND_SOC_DAPM_POST_PMU: ++ msleep(RT9120_AMPON_WAITMS); ++ break; ++ case SND_SOC_DAPM_POST_PMD: ++ msleep(RT9120_AMPOFF_WAITMS); ++ break; ++ default: ++ break; ++ } ++ ++ return 0; ++} ++ ++static const struct snd_soc_dapm_widget rt9120_dapm_widgets[] = { ++ SND_SOC_DAPM_MIXER("DMIX", SND_SOC_NOPM, 0, 0, NULL, 0), ++ SND_SOC_DAPM_DAC("LDAC", NULL, SND_SOC_NOPM, 0, 0), ++ SND_SOC_DAPM_DAC("RDAC", NULL, SND_SOC_NOPM, 0, 0), ++ SND_SOC_DAPM_SUPPLY("PWND", RT9120_REG_SYSCTL, 6, 1, ++ internal_power_event, SND_SOC_DAPM_PRE_PMU | ++ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), ++ SND_SOC_DAPM_PGA("SPKL PA", SND_SOC_NOPM, 0, 0, NULL, 0), ++ SND_SOC_DAPM_PGA("SPKR PA", SND_SOC_NOPM, 0, 0, NULL, 0), ++ SND_SOC_DAPM_OUTPUT("SPKL"), ++ SND_SOC_DAPM_OUTPUT("SPKR"), ++}; ++ ++static const struct snd_soc_dapm_route rt9120_dapm_routes[] = { ++ { "DMIX", NULL, "AIF Playback" }, ++ /* SPKL */ ++ { "LDAC", NULL, "PWND" }, ++ { "LDAC", NULL, "DMIX" }, ++ { "SPKL PA", NULL, "LDAC" }, ++ { "SPKL", NULL, "SPKL PA" }, ++ /* SPKR */ ++ { "RDAC", NULL, "PWND" }, ++ { "RDAC", NULL, "DMIX" }, ++ { "SPKR PA", NULL, "RDAC" }, ++ { "SPKR", NULL, "SPKR PA" }, ++ /* Cap */ ++ { "AIF Capture", NULL, "LDAC" }, ++ { "AIF Capture", NULL, "RDAC" }, ++}; ++ ++static int rt9120_codec_probe(struct snd_soc_component *comp) ++{ ++ struct rt9120_data *data = snd_soc_component_get_drvdata(comp); ++ ++ snd_soc_component_init_regmap(comp, data->regmap); ++ ++ /* Internal setting */ ++ snd_soc_component_write(comp, RT9120_REG_INTERNAL1, 0x03); ++ snd_soc_component_write(comp, RT9120_REG_INTERNAL0, 0x69); ++ return 0; ++} ++ ++static const struct snd_soc_component_driver rt9120_component_driver = { ++ .probe = rt9120_codec_probe, ++ .controls = rt9120_snd_controls, ++ .num_controls = ARRAY_SIZE(rt9120_snd_controls), ++ .dapm_widgets = rt9120_dapm_widgets, ++ .num_dapm_widgets = ARRAY_SIZE(rt9120_dapm_widgets), ++ .dapm_routes = rt9120_dapm_routes, ++ .num_dapm_routes = ARRAY_SIZE(rt9120_dapm_routes), ++}; ++ ++static int rt9120_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) ++{ ++ struct snd_soc_component *comp = dai->component; ++ unsigned int format; ++ ++ switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { ++ case SND_SOC_DAIFMT_I2S: ++ format = RT9120_CFG_FMT_I2S; ++ break; ++ case SND_SOC_DAIFMT_LEFT_J: ++ format = RT9120_CFG_FMT_LEFTJ; ++ break; ++ case SND_SOC_DAIFMT_RIGHT_J: ++ format = RT9120_CFG_FMT_RIGHTJ; ++ break; ++ case SND_SOC_DAIFMT_DSP_A: ++ format = RT9120_CFG_FMT_DSPA; ++ break; ++ case SND_SOC_DAIFMT_DSP_B: ++ format = RT9120_CFG_FMT_DSPB; ++ break; ++ default: ++ dev_err(dai->dev, "Unknown dai format\n"); ++ return -EINVAL; ++ } ++ ++ snd_soc_component_update_bits(comp, RT9120_REG_I2SFMT, ++ RT9120_I2SFMT_MASK, ++ format << RT9120_I2SFMT_SHIFT); ++ return 0; ++} ++ ++static int rt9120_hw_params(struct snd_pcm_substream *substream, ++ struct snd_pcm_hw_params *param, ++ struct snd_soc_dai *dai) ++{ ++ struct snd_soc_component *comp = dai->component; ++ unsigned int param_width, param_slot_width; ++ int width; ++ ++ switch (width = params_width(param)) { ++ case 16: ++ param_width = RT9120_CFG_AUDBIT_16; ++ break; ++ case 20: ++ param_width = RT9120_CFG_AUDBIT_20; ++ break; ++ case 24: ++ case 32: ++ param_width = RT9120_CFG_AUDBIT_24; ++ break; ++ default: ++ dev_err(dai->dev, "Unsupported data width [%d]\n", width); ++ return -EINVAL; ++ } ++ ++ snd_soc_component_update_bits(comp, RT9120_REG_I2SFMT, ++ RT9120_AUDBIT_MASK, param_width); ++ ++ switch (width = params_physical_width(param)) { ++ case 16: ++ param_slot_width = RT9120_CFG_WORDLEN_16; ++ break; ++ case 24: ++ param_slot_width = RT9120_CFG_WORDLEN_24; ++ break; ++ case 32: ++ param_slot_width = RT9120_CFG_WORDLEN_32; ++ break; ++ default: ++ dev_err(dai->dev, "Unsupported slot width [%d]\n", width); ++ return -EINVAL; ++ } ++ ++ snd_soc_component_update_bits(comp, RT9120_REG_I2SWL, ++ RT9120_AUDWL_MASK, param_slot_width); ++ return 0; ++} ++ ++static const struct snd_soc_dai_ops rt9120_dai_ops = { ++ .set_fmt = rt9120_set_fmt, ++ .hw_params = rt9120_hw_params, ++}; ++ ++static struct snd_soc_dai_driver rt9120_dai = { ++ .name = "rt9120_aif", ++ .playback = { ++ .stream_name = "AIF Playback", ++ .rates = RT9120_RATES_MASK, ++ .formats = RT9120_FMTS_MASK, ++ .rate_max = 192000, ++ .rate_min = 8000, ++ .channels_min = 1, ++ .channels_max = 2, ++ }, ++ .capture = { ++ .stream_name = "AIF Capture", ++ .rates = RT9120_RATES_MASK, ++ .formats = RT9120_FMTS_MASK, ++ .rate_max = 192000, ++ .rate_min = 8000, ++ .channels_min = 1, ++ .channels_max = 2, ++ }, ++ .ops = &rt9120_dai_ops, ++ .symmetric_rate = 1, ++ .symmetric_sample_bits = 1, ++}; ++ ++static const struct regmap_range rt9120_rd_yes_ranges[] = { ++ regmap_reg_range(0x00, 0x0C), ++ regmap_reg_range(0x10, 0x15), ++ regmap_reg_range(0x20, 0x27), ++ regmap_reg_range(0x30, 0x38), ++ regmap_reg_range(0x3A, 0x40), ++ regmap_reg_range(0x65, 0x65), ++ regmap_reg_range(0x69, 0x69), ++ regmap_reg_range(0x6C, 0x6C) ++}; ++ ++static const struct regmap_access_table rt9120_rd_table = { ++ .yes_ranges = rt9120_rd_yes_ranges, ++ .n_yes_ranges = ARRAY_SIZE(rt9120_rd_yes_ranges), ++}; ++ ++static const struct regmap_range rt9120_wr_yes_ranges[] = { ++ regmap_reg_range(0x00, 0x00), ++ regmap_reg_range(0x02, 0x0A), ++ regmap_reg_range(0x10, 0x15), ++ regmap_reg_range(0x20, 0x27), ++ regmap_reg_range(0x30, 0x38), ++ regmap_reg_range(0x3A, 0x3D), ++ regmap_reg_range(0x40, 0x40), ++ regmap_reg_range(0x65, 0x65), ++ regmap_reg_range(0x69, 0x69), ++ regmap_reg_range(0x6C, 0x6C) ++}; ++ ++static const struct regmap_access_table rt9120_wr_table = { ++ .yes_ranges = rt9120_wr_yes_ranges, ++ .n_yes_ranges = ARRAY_SIZE(rt9120_wr_yes_ranges), ++}; ++ ++static int rt9120_get_reg_size(unsigned int reg) ++{ ++ switch (reg) { ++ case 0x00: ++ case 0x09: ++ case 0x20 ... 0x27: ++ return 2; ++ case 0x30 ... 0x3D: ++ return 3; ++ case 0x3E ... 0x3F: ++ return 4; ++ default: ++ return 1; ++ } ++} ++ ++static int rt9120_reg_read(void *context, unsigned int reg, unsigned int *val) ++{ ++ struct rt9120_data *data = context; ++ struct i2c_client *i2c = to_i2c_client(data->dev); ++ int size = rt9120_get_reg_size(reg); ++ u8 raw[4] = {0}; ++ int ret; ++ ++ ret = i2c_smbus_read_i2c_block_data(i2c, reg, size, raw); ++ if (ret < 0) ++ return ret; ++ else if (ret != size) ++ return -EIO; ++ ++ switch (size) { ++ case 4: ++ *val = be32_to_cpup((__be32 *)raw); ++ break; ++ case 3: ++ *val = raw[0] << 16 | raw[1] << 8 | raw[0]; ++ break; ++ case 2: ++ *val = be16_to_cpup((__be16 *)raw); ++ break; ++ default: ++ *val = raw[0]; ++ } ++ ++ return 0; ++} ++ ++static int rt9120_reg_write(void *context, unsigned int reg, unsigned int val) ++{ ++ struct rt9120_data *data = context; ++ struct i2c_client *i2c = to_i2c_client(data->dev); ++ int size = rt9120_get_reg_size(reg); ++ __be32 be32_val; ++ u8 *rawp = (u8 *)&be32_val; ++ int offs = 4 - size; ++ ++ be32_val = cpu_to_be32(val); ++ return i2c_smbus_write_i2c_block_data(i2c, reg, size, rawp + offs); ++} ++ ++static const struct regmap_config rt9120_regmap_config = { ++ .reg_bits = 8, ++ .val_bits = 32, ++ .max_register = RT9120_REG_UVPOPT, ++ ++ .reg_read = rt9120_reg_read, ++ .reg_write = rt9120_reg_write, ++ ++ .wr_table = &rt9120_wr_table, ++ .rd_table = &rt9120_rd_table, ++}; ++ ++static int rt9120_check_vendor_info(struct rt9120_data *data) ++{ ++ unsigned int devid; ++ int ret; ++ ++ ret = regmap_read(data->regmap, RT9120_REG_DEVID, &devid); ++ if (ret) ++ return ret; ++ ++ if ((devid & RT9120_VID_MASK) != RT9120_VENDOR_ID) { ++ dev_err(data->dev, "DEVID not correct [0x%04x]\n", devid); ++ return -ENODEV; ++ } ++ ++ return 0; ++} ++ ++static int rt9120_do_register_reset(struct rt9120_data *data) ++{ ++ int ret; ++ ++ ret = regmap_write(data->regmap, RT9120_REG_SWRESET, ++ RT9120_SWRST_MASK); ++ if (ret) ++ return ret; ++ ++ msleep(RT9120_RESET_WAITMS); ++ return 0; ++} ++ ++static int rt9120_probe(struct i2c_client *i2c) ++{ ++ struct rt9120_data *data; ++ struct gpio_desc *pwdnn_gpio; ++ struct regulator *dvdd_supply; ++ int dvdd_supply_volt, ret; ++ ++ data = devm_kzalloc(&i2c->dev, sizeof(*data), GFP_KERNEL); ++ if (!data) ++ return -ENOMEM; ++ ++ data->dev = &i2c->dev; ++ i2c_set_clientdata(i2c, data); ++ ++ pwdnn_gpio = devm_gpiod_get_optional(&i2c->dev, "pwdnn", ++ GPIOD_OUT_HIGH); ++ if (IS_ERR(pwdnn_gpio)) { ++ dev_err(&i2c->dev, "Failed to initialize 'pwdnn' gpio\n"); ++ return PTR_ERR(pwdnn_gpio); ++ } else if (pwdnn_gpio) { ++ dev_dbg(&i2c->dev, "'pwdnn' from low to high, wait chip on\n"); ++ msleep(RT9120_CHIPON_WAITMS); ++ } ++ ++ data->regmap = devm_regmap_init(&i2c->dev, NULL, data, ++ &rt9120_regmap_config); ++ if (IS_ERR(data->regmap)) { ++ ret = PTR_ERR(data->regmap); ++ dev_err(&i2c->dev, "Failed to init regmap [%d]\n", ret); ++ return ret; ++ } ++ ++ ret = rt9120_check_vendor_info(data); ++ if (ret) { ++ dev_err(&i2c->dev, "Failed to check vendor info\n"); ++ return ret; ++ } ++ ++ ret = rt9120_do_register_reset(data); ++ if (ret) { ++ dev_err(&i2c->dev, "Failed to do register reset\n"); ++ return ret; ++ } ++ ++ dvdd_supply = devm_regulator_get(&i2c->dev, "dvdd"); ++ if (IS_ERR(dvdd_supply)) { ++ dev_err(&i2c->dev, "No dvdd regulator found\n"); ++ return PTR_ERR(dvdd_supply); ++ } ++ ++ dvdd_supply_volt = regulator_get_voltage(dvdd_supply); ++ if (dvdd_supply_volt <= RT9120_LVAPP_THRESUV) { ++ dev_dbg(&i2c->dev, "dvdd low voltage design\n"); ++ ret = regmap_update_bits(data->regmap, RT9120_REG_UVPOPT, ++ RT9120_DVDD_UVSEL_MASK, 0); ++ if (ret) { ++ dev_err(&i2c->dev, "Failed to config dvdd uvsel\n"); ++ return ret; ++ } ++ } ++ ++ return devm_snd_soc_register_component(&i2c->dev, ++ &rt9120_component_driver, ++ &rt9120_dai, 1); ++} ++ ++static const struct of_device_id __maybe_unused rt9120_device_table[] = { ++ { .compatible = "richtek,rt9120", }, ++ { } ++}; ++MODULE_DEVICE_TABLE(of, rt9120_device_table); ++ ++static struct i2c_driver rt9120_driver = { ++ .driver = { ++ .name = "rt9120", ++ .of_match_table = rt9120_device_table, ++ }, ++ .probe_new = rt9120_probe, ++}; ++module_i2c_driver(rt9120_driver); ++ ++MODULE_AUTHOR("ChiYuan Huang "); ++MODULE_DESCRIPTION("RT9120 Audio Amplifier Driver"); ++MODULE_LICENSE("GPL"); +-- +2.42.0 + diff --git a/queue-5.15/mcb-lpc-reallocate-memory-region-to-avoid-memory-ove.patch b/queue-5.15/mcb-lpc-reallocate-memory-region-to-avoid-memory-ove.patch new file mode 100644 index 00000000000..5023f241ddc --- /dev/null +++ b/queue-5.15/mcb-lpc-reallocate-memory-region-to-avoid-memory-ove.patch @@ -0,0 +1,93 @@ +From 5a2ce3cfd03d96505f4dbf177a9758e6fea97a3a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 11 Apr 2023 10:33:29 +0200 +Subject: mcb-lpc: Reallocate memory region to avoid memory overlapping +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Rodríguez Barbarin, José Javier + +[ Upstream commit 2025b2ca8004c04861903d076c67a73a0ec6dfca ] + +mcb-lpc requests a fixed-size memory region to parse the chameleon +table, however, if the chameleon table is smaller that the allocated +region, it could overlap with the IP Cores' memory regions. + +After parsing the chameleon table, drop/reallocate the memory region +with the actual chameleon table size. + +Co-developed-by: Jorge Sanjuan Garcia +Signed-off-by: Jorge Sanjuan Garcia +Signed-off-by: Javier Rodriguez +Signed-off-by: Johannes Thumshirn +Link: https://lore.kernel.org/r/20230411083329.4506-4-jth@kernel.org +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + drivers/mcb/mcb-lpc.c | 35 +++++++++++++++++++++++++++++++---- + 1 file changed, 31 insertions(+), 4 deletions(-) + +diff --git a/drivers/mcb/mcb-lpc.c b/drivers/mcb/mcb-lpc.c +index 53decd89876ee..a851e02364642 100644 +--- a/drivers/mcb/mcb-lpc.c ++++ b/drivers/mcb/mcb-lpc.c +@@ -23,7 +23,7 @@ static int mcb_lpc_probe(struct platform_device *pdev) + { + struct resource *res; + struct priv *priv; +- int ret = 0; ++ int ret = 0, table_size; + + priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); + if (!priv) +@@ -58,16 +58,43 @@ static int mcb_lpc_probe(struct platform_device *pdev) + + ret = chameleon_parse_cells(priv->bus, priv->mem->start, priv->base); + if (ret < 0) { +- mcb_release_bus(priv->bus); +- return ret; ++ goto out_mcb_bus; + } + +- dev_dbg(&pdev->dev, "Found %d cells\n", ret); ++ table_size = ret; ++ ++ if (table_size < CHAM_HEADER_SIZE) { ++ /* Release the previous resources */ ++ devm_iounmap(&pdev->dev, priv->base); ++ devm_release_mem_region(&pdev->dev, priv->mem->start, resource_size(priv->mem)); ++ ++ /* Then, allocate it again with the actual chameleon table size */ ++ res = devm_request_mem_region(&pdev->dev, priv->mem->start, ++ table_size, ++ KBUILD_MODNAME); ++ if (!res) { ++ dev_err(&pdev->dev, "Failed to request PCI memory\n"); ++ ret = -EBUSY; ++ goto out_mcb_bus; ++ } ++ ++ priv->base = devm_ioremap(&pdev->dev, priv->mem->start, table_size); ++ if (!priv->base) { ++ dev_err(&pdev->dev, "Cannot ioremap\n"); ++ ret = -ENOMEM; ++ goto out_mcb_bus; ++ } ++ ++ platform_set_drvdata(pdev, priv); ++ } + + mcb_bus_add_devices(priv->bus); + + return 0; + ++out_mcb_bus: ++ mcb_release_bus(priv->bus); ++ return ret; + } + + static int mcb_lpc_remove(struct platform_device *pdev) +-- +2.42.0 + diff --git a/queue-5.15/mcb-return-actual-parsed-size-when-reading-chameleon.patch b/queue-5.15/mcb-return-actual-parsed-size-when-reading-chameleon.patch new file mode 100644 index 00000000000..a6353402964 --- /dev/null +++ b/queue-5.15/mcb-return-actual-parsed-size-when-reading-chameleon.patch @@ -0,0 +1,81 @@ +From 5271fed77f4706a29b66cdfe52c1153935822c65 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 11 Apr 2023 10:33:27 +0200 +Subject: mcb: Return actual parsed size when reading chameleon table +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Rodríguez Barbarin, José Javier + +[ Upstream commit a889c276d33d333ae96697510f33533f6e9d9591 ] + +The function chameleon_parse_cells() returns the number of cells +parsed which has an undetermined size. This return value is only +used for error checking but the number of cells is never used. + +Change return value to be number of bytes parsed to allow for +memory management improvements. + +Co-developed-by: Jorge Sanjuan Garcia +Signed-off-by: Jorge Sanjuan Garcia +Signed-off-by: Javier Rodriguez +Signed-off-by: Johannes Thumshirn +Link: https://lore.kernel.org/r/20230411083329.4506-2-jth@kernel.org +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + drivers/mcb/mcb-parse.c | 15 ++++++++++----- + 1 file changed, 10 insertions(+), 5 deletions(-) + +diff --git a/drivers/mcb/mcb-parse.c b/drivers/mcb/mcb-parse.c +index c41cbacc75a2c..656b6b71c7682 100644 +--- a/drivers/mcb/mcb-parse.c ++++ b/drivers/mcb/mcb-parse.c +@@ -128,7 +128,7 @@ static void chameleon_parse_bar(void __iomem *base, + } + } + +-static int chameleon_get_bar(char __iomem **base, phys_addr_t mapbase, ++static int chameleon_get_bar(void __iomem **base, phys_addr_t mapbase, + struct chameleon_bar **cb) + { + struct chameleon_bar *c; +@@ -177,12 +177,13 @@ int chameleon_parse_cells(struct mcb_bus *bus, phys_addr_t mapbase, + { + struct chameleon_fpga_header *header; + struct chameleon_bar *cb; +- char __iomem *p = base; ++ void __iomem *p = base; + int num_cells = 0; + uint32_t dtype; + int bar_count; + int ret; + u32 hsize; ++ u32 table_size; + + hsize = sizeof(struct chameleon_fpga_header); + +@@ -237,12 +238,16 @@ int chameleon_parse_cells(struct mcb_bus *bus, phys_addr_t mapbase, + num_cells++; + } + +- if (num_cells == 0) +- num_cells = -EINVAL; ++ if (num_cells == 0) { ++ ret = -EINVAL; ++ goto free_bar; ++ } + ++ table_size = p - base; ++ pr_debug("%d cell(s) found. Chameleon table size: 0x%04x bytes\n", num_cells, table_size); + kfree(cb); + kfree(header); +- return num_cells; ++ return table_size; + + free_bar: + kfree(cb); +-- +2.42.0 + diff --git a/queue-5.15/mmc-block-ioctl-do-write-error-check-for-spi.patch b/queue-5.15/mmc-block-ioctl-do-write-error-check-for-spi.patch new file mode 100644 index 00000000000..148b51e15c8 --- /dev/null +++ b/queue-5.15/mmc-block-ioctl-do-write-error-check-for-spi.patch @@ -0,0 +1,52 @@ +From c6f89c1cf0b5d658c626c387c3b700cb6e237837 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 25 May 2023 09:56:04 +0000 +Subject: mmc: block: ioctl: do write error check for spi + +From: Christian Loehle + +[ Upstream commit 568898cbc8b570311b3b94a3202b8233f4168144 ] + +SPI doesn't have the usual PROG path we can check for error bits +after moving back to TRAN. Instead it holds the line LOW until +completion. We can then check if the card shows any errors or +is in IDLE state, indicating the line is no longer LOW because +the card was reset. + +Signed-off-by: Christian Loehle +Cc: stable@vger.kernel.org +Link: https://lore.kernel.org/r/55920f880c9742f486f64aa44e25508e@hyperstone.com +Signed-off-by: Ulf Hansson +Stable-dep-of: f19c5a73e6f7 ("mmc: core: Fix error propagation for some ioctl commands") +Signed-off-by: Sasha Levin +--- + drivers/mmc/core/block.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/drivers/mmc/core/block.c b/drivers/mmc/core/block.c +index 466705b60fb7c..d2d428fafe7fc 100644 +--- a/drivers/mmc/core/block.c ++++ b/drivers/mmc/core/block.c +@@ -179,6 +179,7 @@ static void mmc_blk_rw_rq_prep(struct mmc_queue_req *mqrq, + int recovery_mode, + struct mmc_queue *mq); + static void mmc_blk_hsq_req_done(struct mmc_request *mrq); ++static int mmc_spi_err_check(struct mmc_card *card); + + static struct mmc_blk_data *mmc_blk_get(struct gendisk *disk) + { +@@ -622,6 +623,11 @@ static int __mmc_blk_ioctl_cmd(struct mmc_card *card, struct mmc_blk_data *md, + if ((card->host->caps & MMC_CAP_WAIT_WHILE_BUSY) && use_r1b_resp) + return 0; + ++ if (mmc_host_is_spi(card->host)) { ++ if (idata->ic.write_flag || r1b_resp || cmd.flags & MMC_RSP_SPI_BUSY) ++ return mmc_spi_err_check(card); ++ return err; ++ } + /* Ensure RPMB/R1B command has completed by polling with CMD13. */ + if (idata->rpmb || r1b_resp) + err = mmc_poll_for_busy(card, busy_timeout_ms, false, +-- +2.42.0 + diff --git a/queue-5.15/mmc-core-adjust-polling-interval-for-cmd1.patch b/queue-5.15/mmc-core-adjust-polling-interval-for-cmd1.patch new file mode 100644 index 00000000000..3e71d63fc38 --- /dev/null +++ b/queue-5.15/mmc-core-adjust-polling-interval-for-cmd1.patch @@ -0,0 +1,159 @@ +From 0e1b1c8d696d3b57537a87da07190aa723dbff6d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 4 Nov 2021 15:32:31 +0900 +Subject: mmc: core: adjust polling interval for CMD1 + +From: Huijin Park + +[ Upstream commit 76bfc7ccc2fa9d382576f6013b57a0ef93d5a722 ] + +In mmc_send_op_cond(), loops are continuously performed at the same +interval of 10 ms. However the behaviour is not good for some eMMC +which can be out from a busy state earlier than 10 ms if normal. + +Rather than fixing about the interval time in mmc_send_op_cond(), +let's instead convert into using the common __mmc_poll_for_busy(). + +The reason for adjusting the interval time is that it is important +to reduce the eMMC initialization time, especially in devices that +use eMMC as rootfs. + +Test log(eMMC:KLM8G1GETF-B041): + +before: 12 ms (0.311016 - 0.298729) +[ 0.295823] mmc0: starting CMD0 arg 00000000 flags 000000c0 +[ 0.298729] mmc0: starting CMD1 arg 40000080 flags 000000e1<-start +[ 0.311016] mmc0: starting CMD1 arg 40000080 flags 000000e1<-finish +[ 0.311336] mmc0: starting CMD2 arg 00000000 flags 00000007 + +after: 2 ms (0.301270 - 0.298762) +[ 0.295862] mmc0: starting CMD0 arg 00000000 flags 000000c0 +[ 0.298762] mmc0: starting CMD1 arg 40000080 flags 000000e1<-start +[ 0.299067] mmc0: starting CMD1 arg 40000080 flags 000000e1 +[ 0.299441] mmc0: starting CMD1 arg 40000080 flags 000000e1 +[ 0.299879] mmc0: starting CMD1 arg 40000080 flags 000000e1 +[ 0.300446] mmc0: starting CMD1 arg 40000080 flags 000000e1 +[ 0.301270] mmc0: starting CMD1 arg 40000080 flags 000000e1<-finish +[ 0.301572] mmc0: starting CMD2 arg 00000000 flags 00000007 + +Signed-off-by: Huijin Park +Link: https://lore.kernel.org/r/20211104063231.2115-3-huijin.park@samsung.com +Signed-off-by: Ulf Hansson +Stable-dep-of: f19c5a73e6f7 ("mmc: core: Fix error propagation for some ioctl commands") +Signed-off-by: Sasha Levin +--- + drivers/mmc/core/mmc_ops.c | 83 +++++++++++++++++++++++++------------- + 1 file changed, 54 insertions(+), 29 deletions(-) + +diff --git a/drivers/mmc/core/mmc_ops.c b/drivers/mmc/core/mmc_ops.c +index 9946733a34c6d..d63d1c735335c 100644 +--- a/drivers/mmc/core/mmc_ops.c ++++ b/drivers/mmc/core/mmc_ops.c +@@ -58,6 +58,12 @@ struct mmc_busy_data { + enum mmc_busy_cmd busy_cmd; + }; + ++struct mmc_op_cond_busy_data { ++ struct mmc_host *host; ++ u32 ocr; ++ struct mmc_command *cmd; ++}; ++ + int __mmc_send_status(struct mmc_card *card, u32 *status, unsigned int retries) + { + int err; +@@ -173,43 +179,62 @@ int mmc_go_idle(struct mmc_host *host) + return err; + } + ++static int __mmc_send_op_cond_cb(void *cb_data, bool *busy) ++{ ++ struct mmc_op_cond_busy_data *data = cb_data; ++ struct mmc_host *host = data->host; ++ struct mmc_command *cmd = data->cmd; ++ u32 ocr = data->ocr; ++ int err = 0; ++ ++ err = mmc_wait_for_cmd(host, cmd, 0); ++ if (err) ++ return err; ++ ++ if (mmc_host_is_spi(host)) { ++ if (!(cmd->resp[0] & R1_SPI_IDLE)) { ++ *busy = false; ++ return 0; ++ } ++ } else { ++ if (cmd->resp[0] & MMC_CARD_BUSY) { ++ *busy = false; ++ return 0; ++ } ++ } ++ ++ *busy = true; ++ ++ /* ++ * According to eMMC specification v5.1 section 6.4.3, we ++ * should issue CMD1 repeatedly in the idle state until ++ * the eMMC is ready. Otherwise some eMMC devices seem to enter ++ * the inactive mode after mmc_init_card() issued CMD0 when ++ * the eMMC device is busy. ++ */ ++ if (!ocr && !mmc_host_is_spi(host)) ++ cmd->arg = cmd->resp[0] | BIT(30); ++ ++ return 0; ++} ++ + int mmc_send_op_cond(struct mmc_host *host, u32 ocr, u32 *rocr) + { + struct mmc_command cmd = {}; +- int i, err = 0; ++ int err = 0; ++ struct mmc_op_cond_busy_data cb_data = { ++ .host = host, ++ .ocr = ocr, ++ .cmd = &cmd ++ }; + + cmd.opcode = MMC_SEND_OP_COND; + cmd.arg = mmc_host_is_spi(host) ? 0 : ocr; + cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R3 | MMC_CMD_BCR; + +- for (i = 100; i; i--) { +- err = mmc_wait_for_cmd(host, &cmd, 0); +- if (err) +- break; +- +- /* wait until reset completes */ +- if (mmc_host_is_spi(host)) { +- if (!(cmd.resp[0] & R1_SPI_IDLE)) +- break; +- } else { +- if (cmd.resp[0] & MMC_CARD_BUSY) +- break; +- } +- +- err = -ETIMEDOUT; +- +- mmc_delay(10); +- +- /* +- * According to eMMC specification v5.1 section 6.4.3, we +- * should issue CMD1 repeatedly in the idle state until +- * the eMMC is ready. Otherwise some eMMC devices seem to enter +- * the inactive mode after mmc_init_card() issued CMD0 when +- * the eMMC device is busy. +- */ +- if (!ocr && !mmc_host_is_spi(host)) +- cmd.arg = cmd.resp[0] | BIT(30); +- } ++ err = __mmc_poll_for_busy(host, 1000, &__mmc_send_op_cond_cb, &cb_data); ++ if (err) ++ return err; + + if (rocr && !mmc_host_is_spi(host)) + *rocr = cmd.resp[0]; +-- +2.42.0 + diff --git a/queue-5.15/mmc-core-align-to-common-busy-polling-behaviour-for-.patch b/queue-5.15/mmc-core-align-to-common-busy-polling-behaviour-for-.patch new file mode 100644 index 00000000000..a60705f38bb --- /dev/null +++ b/queue-5.15/mmc-core-align-to-common-busy-polling-behaviour-for-.patch @@ -0,0 +1,95 @@ +From edb7b47f5e5c4f52f2119266130ff8dd117df53d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 13 Feb 2023 14:37:07 +0100 +Subject: mmc: core: Align to common busy polling behaviour for mmc ioctls + +From: Ulf Hansson + +[ Upstream commit 51f5b3056790bc0518e49587996f1e6f3058cca9 ] + +Let's align to the common busy polling behaviour for mmc ioctls, by +updating the below two corresponding parts, that comes into play when using +an R1B response for a command. + +*) A command with an R1B response should be prepared by calling +mmc_prepare_busy_cmd(), which make us respects the host's busy timeout +constraints. +**) When an R1B response is being used and the host also supports HW busy +detection, we should skip to poll for busy completion. + +Suggested-by: Christian Loehle +Signed-off-by: Ulf Hansson +Reviewed-by: Christian Loehle +Link: https://lore.kernel.org/r/20230213133707.27857-1-ulf.hansson@linaro.org +Stable-dep-of: f19c5a73e6f7 ("mmc: core: Fix error propagation for some ioctl commands") +Signed-off-by: Sasha Levin +--- + drivers/mmc/core/block.c | 25 +++++++++++++++++-------- + drivers/mmc/core/mmc_ops.c | 1 + + 2 files changed, 18 insertions(+), 8 deletions(-) + +diff --git a/drivers/mmc/core/block.c b/drivers/mmc/core/block.c +index c7c23acfd03ed..466705b60fb7c 100644 +--- a/drivers/mmc/core/block.c ++++ b/drivers/mmc/core/block.c +@@ -470,6 +470,8 @@ static int __mmc_blk_ioctl_cmd(struct mmc_card *card, struct mmc_blk_data *md, + struct mmc_data data = {}; + struct mmc_request mrq = {}; + struct scatterlist sg; ++ bool r1b_resp, use_r1b_resp = false; ++ unsigned int busy_timeout_ms; + int err; + unsigned int target_part; + +@@ -558,6 +560,13 @@ static int __mmc_blk_ioctl_cmd(struct mmc_card *card, struct mmc_blk_data *md, + (cmd.opcode == MMC_SWITCH)) + return mmc_sanitize(card, idata->ic.cmd_timeout_ms); + ++ /* If it's an R1B response we need some more preparations. */ ++ busy_timeout_ms = idata->ic.cmd_timeout_ms ? : MMC_BLK_TIMEOUT_MS; ++ r1b_resp = (cmd.flags & MMC_RSP_R1B) == MMC_RSP_R1B; ++ if (r1b_resp) ++ use_r1b_resp = mmc_prepare_busy_cmd(card->host, &cmd, ++ busy_timeout_ms); ++ + mmc_wait_for_req(card->host, &mrq); + memcpy(&idata->ic.response, cmd.resp, sizeof(cmd.resp)); + +@@ -609,14 +618,14 @@ static int __mmc_blk_ioctl_cmd(struct mmc_card *card, struct mmc_blk_data *md, + if (idata->ic.postsleep_min_us) + usleep_range(idata->ic.postsleep_min_us, idata->ic.postsleep_max_us); + +- if (idata->rpmb || (cmd.flags & MMC_RSP_R1B) == MMC_RSP_R1B) { +- /* +- * Ensure RPMB/R1B command has completed by polling CMD13 "Send Status". Here we +- * allow to override the default timeout value if a custom timeout is specified. +- */ +- err = mmc_poll_for_busy(card, idata->ic.cmd_timeout_ms ? : MMC_BLK_TIMEOUT_MS, +- false, MMC_BUSY_IO); +- } ++ /* No need to poll when using HW busy detection. */ ++ if ((card->host->caps & MMC_CAP_WAIT_WHILE_BUSY) && use_r1b_resp) ++ return 0; ++ ++ /* Ensure RPMB/R1B command has completed by polling with CMD13. */ ++ if (idata->rpmb || r1b_resp) ++ err = mmc_poll_for_busy(card, busy_timeout_ms, false, ++ MMC_BUSY_IO); + + return err; + } +diff --git a/drivers/mmc/core/mmc_ops.c b/drivers/mmc/core/mmc_ops.c +index 180d7e9d3400a..dd6b3e116fcd5 100644 +--- a/drivers/mmc/core/mmc_ops.c ++++ b/drivers/mmc/core/mmc_ops.c +@@ -575,6 +575,7 @@ bool mmc_prepare_busy_cmd(struct mmc_host *host, struct mmc_command *cmd, + cmd->busy_timeout = timeout_ms; + return true; + } ++EXPORT_SYMBOL_GPL(mmc_prepare_busy_cmd); + + /** + * __mmc_switch - modify EXT_CSD register +-- +2.42.0 + diff --git a/queue-5.15/mmc-core-change-__mmc_poll_for_busy-parameter-type.patch b/queue-5.15/mmc-core-change-__mmc_poll_for_busy-parameter-type.patch new file mode 100644 index 00000000000..eb6f40e788f --- /dev/null +++ b/queue-5.15/mmc-core-change-__mmc_poll_for_busy-parameter-type.patch @@ -0,0 +1,116 @@ +From e00fa5b928fe670ad8969dd10ad31190e73314e9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 4 Nov 2021 15:32:30 +0900 +Subject: mmc: core: change __mmc_poll_for_busy() parameter type + +From: Huijin Park + +[ Upstream commit 2ebbdace5cc05caea9d12f536a8d0b9a3d930a29 ] + +This patch changes the __mmc_poll_for_busy() first parameter type +from 'struct mmc_card*' to 'struct mmc_host*'. +Because the function refers only 'struct mmc_host' to get hostname. + +Signed-off-by: Huijin Park +Link: https://lore.kernel.org/r/20211104063231.2115-2-huijin.park@samsung.com +Signed-off-by: Ulf Hansson +Stable-dep-of: f19c5a73e6f7 ("mmc: core: Fix error propagation for some ioctl commands") +Signed-off-by: Sasha Levin +--- + drivers/mmc/core/block.c | 4 ++-- + drivers/mmc/core/mmc.c | 2 +- + drivers/mmc/core/mmc_ops.c | 6 +++--- + drivers/mmc/core/mmc_ops.h | 2 +- + drivers/mmc/core/sd.c | 2 +- + 5 files changed, 8 insertions(+), 8 deletions(-) + +diff --git a/drivers/mmc/core/block.c b/drivers/mmc/core/block.c +index 25077a1a3d821..78af9842057ec 100644 +--- a/drivers/mmc/core/block.c ++++ b/drivers/mmc/core/block.c +@@ -1955,8 +1955,8 @@ static int mmc_blk_card_busy(struct mmc_card *card, struct request *req) + + cb_data.card = card; + cb_data.status = 0; +- err = __mmc_poll_for_busy(card, MMC_BLK_TIMEOUT_MS, &mmc_blk_busy_cb, +- &cb_data); ++ err = __mmc_poll_for_busy(card->host, MMC_BLK_TIMEOUT_MS, ++ &mmc_blk_busy_cb, &cb_data); + + /* + * Do not assume data transferred correctly if there are any error bits +diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c +index 5074b3ce38ea0..c28d7218dce39 100644 +--- a/drivers/mmc/core/mmc.c ++++ b/drivers/mmc/core/mmc.c +@@ -1969,7 +1969,7 @@ static int mmc_sleep(struct mmc_host *host) + goto out_release; + } + +- err = __mmc_poll_for_busy(card, timeout_ms, &mmc_sleep_busy_cb, host); ++ err = __mmc_poll_for_busy(host, timeout_ms, &mmc_sleep_busy_cb, host); + + out_release: + mmc_retune_release(host); +diff --git a/drivers/mmc/core/mmc_ops.c b/drivers/mmc/core/mmc_ops.c +index 0c54858e89c06..9946733a34c6d 100644 +--- a/drivers/mmc/core/mmc_ops.c ++++ b/drivers/mmc/core/mmc_ops.c +@@ -470,11 +470,10 @@ static int mmc_busy_cb(void *cb_data, bool *busy) + return 0; + } + +-int __mmc_poll_for_busy(struct mmc_card *card, unsigned int timeout_ms, ++int __mmc_poll_for_busy(struct mmc_host *host, unsigned int timeout_ms, + int (*busy_cb)(void *cb_data, bool *busy), + void *cb_data) + { +- struct mmc_host *host = card->host; + int err; + unsigned long timeout; + unsigned int udelay = 32, udelay_max = 32768; +@@ -515,13 +514,14 @@ EXPORT_SYMBOL_GPL(__mmc_poll_for_busy); + int mmc_poll_for_busy(struct mmc_card *card, unsigned int timeout_ms, + bool retry_crc_err, enum mmc_busy_cmd busy_cmd) + { ++ struct mmc_host *host = card->host; + struct mmc_busy_data cb_data; + + cb_data.card = card; + cb_data.retry_crc_err = retry_crc_err; + cb_data.busy_cmd = busy_cmd; + +- return __mmc_poll_for_busy(card, timeout_ms, &mmc_busy_cb, &cb_data); ++ return __mmc_poll_for_busy(host, timeout_ms, &mmc_busy_cb, &cb_data); + } + EXPORT_SYMBOL_GPL(mmc_poll_for_busy); + +diff --git a/drivers/mmc/core/mmc_ops.h b/drivers/mmc/core/mmc_ops.h +index ae25ffc2e8704..fd266c7fa41a5 100644 +--- a/drivers/mmc/core/mmc_ops.h ++++ b/drivers/mmc/core/mmc_ops.h +@@ -42,7 +42,7 @@ int mmc_get_ext_csd(struct mmc_card *card, u8 **new_ext_csd); + int mmc_switch_status(struct mmc_card *card, bool crc_err_fatal); + bool mmc_prepare_busy_cmd(struct mmc_host *host, struct mmc_command *cmd, + unsigned int timeout_ms); +-int __mmc_poll_for_busy(struct mmc_card *card, unsigned int timeout_ms, ++int __mmc_poll_for_busy(struct mmc_host *host, unsigned int timeout_ms, + int (*busy_cb)(void *cb_data, bool *busy), + void *cb_data); + int mmc_poll_for_busy(struct mmc_card *card, unsigned int timeout_ms, +diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c +index 592166e53dce8..03636a432e2da 100644 +--- a/drivers/mmc/core/sd.c ++++ b/drivers/mmc/core/sd.c +@@ -1667,7 +1667,7 @@ static int sd_poweroff_notify(struct mmc_card *card) + + cb_data.card = card; + cb_data.reg_buf = reg_buf; +- err = __mmc_poll_for_busy(card, SD_POWEROFF_NOTIFY_TIMEOUT_MS, ++ err = __mmc_poll_for_busy(card->host, SD_POWEROFF_NOTIFY_TIMEOUT_MS, + &sd_busy_poweroff_notify_cb, &cb_data); + + out: +-- +2.42.0 + diff --git a/queue-5.15/mmc-core-fix-error-propagation-for-some-ioctl-comman.patch b/queue-5.15/mmc-core-fix-error-propagation-for-some-ioctl-comman.patch new file mode 100644 index 00000000000..315fd025ab4 --- /dev/null +++ b/queue-5.15/mmc-core-fix-error-propagation-for-some-ioctl-comman.patch @@ -0,0 +1,100 @@ +From 9cf75b1a2570c8127e3e908deb124a7c8eac132f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 13 Sep 2023 13:29:21 +0200 +Subject: mmc: core: Fix error propagation for some ioctl commands + +From: Ulf Hansson + +[ Upstream commit f19c5a73e6f78d69efce66cfdce31148c76a61a6 ] + +Userspace has currently no way of checking the internal R1 response error +bits for some commands. This is a problem for some commands, like RPMB for +example. Typically, we may detect that the busy completion has successfully +ended, while in fact the card did not complete the requested operation. + +To fix the problem, let's always poll with CMD13 for these commands and +during the polling, let's also aggregate the R1 response bits. Before +completing the ioctl request, let's propagate the R1 response bits too. + +Reviewed-by: Avri Altman +Co-developed-by: Christian Loehle +Signed-off-by: Christian Loehle +Signed-off-by: Ulf Hansson +Cc: stable@vger.kernel.org +Link: https://lore.kernel.org/r/20230913112921.553019-1-ulf.hansson@linaro.org +Signed-off-by: Sasha Levin +--- + drivers/mmc/core/block.c | 31 ++++++++++++++++++++----------- + 1 file changed, 20 insertions(+), 11 deletions(-) + +diff --git a/drivers/mmc/core/block.c b/drivers/mmc/core/block.c +index d2d428fafe7fc..d82d567f0db49 100644 +--- a/drivers/mmc/core/block.c ++++ b/drivers/mmc/core/block.c +@@ -180,6 +180,7 @@ static void mmc_blk_rw_rq_prep(struct mmc_queue_req *mqrq, + struct mmc_queue *mq); + static void mmc_blk_hsq_req_done(struct mmc_request *mrq); + static int mmc_spi_err_check(struct mmc_card *card); ++static int mmc_blk_busy_cb(void *cb_data, bool *busy); + + static struct mmc_blk_data *mmc_blk_get(struct gendisk *disk) + { +@@ -471,7 +472,7 @@ static int __mmc_blk_ioctl_cmd(struct mmc_card *card, struct mmc_blk_data *md, + struct mmc_data data = {}; + struct mmc_request mrq = {}; + struct scatterlist sg; +- bool r1b_resp, use_r1b_resp = false; ++ bool r1b_resp; + unsigned int busy_timeout_ms; + int err; + unsigned int target_part; +@@ -565,8 +566,7 @@ static int __mmc_blk_ioctl_cmd(struct mmc_card *card, struct mmc_blk_data *md, + busy_timeout_ms = idata->ic.cmd_timeout_ms ? : MMC_BLK_TIMEOUT_MS; + r1b_resp = (cmd.flags & MMC_RSP_R1B) == MMC_RSP_R1B; + if (r1b_resp) +- use_r1b_resp = mmc_prepare_busy_cmd(card->host, &cmd, +- busy_timeout_ms); ++ mmc_prepare_busy_cmd(card->host, &cmd, busy_timeout_ms); + + mmc_wait_for_req(card->host, &mrq); + memcpy(&idata->ic.response, cmd.resp, sizeof(cmd.resp)); +@@ -619,19 +619,28 @@ static int __mmc_blk_ioctl_cmd(struct mmc_card *card, struct mmc_blk_data *md, + if (idata->ic.postsleep_min_us) + usleep_range(idata->ic.postsleep_min_us, idata->ic.postsleep_max_us); + +- /* No need to poll when using HW busy detection. */ +- if ((card->host->caps & MMC_CAP_WAIT_WHILE_BUSY) && use_r1b_resp) +- return 0; +- + if (mmc_host_is_spi(card->host)) { + if (idata->ic.write_flag || r1b_resp || cmd.flags & MMC_RSP_SPI_BUSY) + return mmc_spi_err_check(card); + return err; + } +- /* Ensure RPMB/R1B command has completed by polling with CMD13. */ +- if (idata->rpmb || r1b_resp) +- err = mmc_poll_for_busy(card, busy_timeout_ms, false, +- MMC_BUSY_IO); ++ ++ /* ++ * Ensure RPMB, writes and R1B responses are completed by polling with ++ * CMD13. Note that, usually we don't need to poll when using HW busy ++ * detection, but here it's needed since some commands may indicate the ++ * error through the R1 status bits. ++ */ ++ if (idata->rpmb || idata->ic.write_flag || r1b_resp) { ++ struct mmc_blk_busy_data cb_data = { ++ .card = card, ++ }; ++ ++ err = __mmc_poll_for_busy(card->host, 0, busy_timeout_ms, ++ &mmc_blk_busy_cb, &cb_data); ++ ++ idata->ic.response[0] = cb_data.status; ++ } + + return err; + } +-- +2.42.0 + diff --git a/queue-5.15/mmc-core-restore-almost-the-busy-polling-for-mmc_sen.patch b/queue-5.15/mmc-core-restore-almost-the-busy-polling-for-mmc_sen.patch new file mode 100644 index 00000000000..fdb8b277b3f --- /dev/null +++ b/queue-5.15/mmc-core-restore-almost-the-busy-polling-for-mmc_sen.patch @@ -0,0 +1,144 @@ +From 5f2b8d5eaedb0c7b50c79bbb2e15b9d6d9c97915 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 4 Mar 2022 11:56:56 +0100 +Subject: mmc: core: Restore (almost) the busy polling for MMC_SEND_OP_COND + +From: Ulf Hansson + +[ Upstream commit 1760fdb6fe9f796fbdb9b4106b3e0bbacc16b55c ] + +Commit 76bfc7ccc2fa ("mmc: core: adjust polling interval for CMD1"), +significantly decreased the polling period from ~10-12ms into just a couple +of us. The purpose was to decrease the total time spent in the busy polling +loop, but unfortunate it has lead to problems, that causes eMMC cards to +never gets out busy and thus fails to be initialized. + +To fix the problem, but also to try to keep some of the new improved +behaviour, let's start by using a polling period of 1-2ms, which then +increases for each loop, according to common polling loop in +__mmc_poll_for_busy(). + +Reported-by: Jean Rene Dawin +Reported-by: H. Nikolaus Schaller +Cc: Huijin Park +Fixes: 76bfc7ccc2fa ("mmc: core: adjust polling interval for CMD1") +Signed-off-by: Ulf Hansson +Tested-by: Jean Rene Dawin +Tested-by: H. Nikolaus Schaller +Link: https://lore.kernel.org/r/20220304105656.149281-1-ulf.hansson@linaro.org +Stable-dep-of: f19c5a73e6f7 ("mmc: core: Fix error propagation for some ioctl commands") +Signed-off-by: Sasha Levin +--- + drivers/mmc/core/block.c | 2 +- + drivers/mmc/core/mmc.c | 2 +- + drivers/mmc/core/mmc_ops.c | 13 +++++++++---- + drivers/mmc/core/mmc_ops.h | 3 ++- + drivers/mmc/core/sd.c | 2 +- + 5 files changed, 14 insertions(+), 8 deletions(-) + +diff --git a/drivers/mmc/core/block.c b/drivers/mmc/core/block.c +index 78af9842057ec..c7c23acfd03ed 100644 +--- a/drivers/mmc/core/block.c ++++ b/drivers/mmc/core/block.c +@@ -1955,7 +1955,7 @@ static int mmc_blk_card_busy(struct mmc_card *card, struct request *req) + + cb_data.card = card; + cb_data.status = 0; +- err = __mmc_poll_for_busy(card->host, MMC_BLK_TIMEOUT_MS, ++ err = __mmc_poll_for_busy(card->host, 0, MMC_BLK_TIMEOUT_MS, + &mmc_blk_busy_cb, &cb_data); + + /* +diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c +index c28d7218dce39..2a6c5d2c5ecf1 100644 +--- a/drivers/mmc/core/mmc.c ++++ b/drivers/mmc/core/mmc.c +@@ -1969,7 +1969,7 @@ static int mmc_sleep(struct mmc_host *host) + goto out_release; + } + +- err = __mmc_poll_for_busy(host, timeout_ms, &mmc_sleep_busy_cb, host); ++ err = __mmc_poll_for_busy(host, 0, timeout_ms, &mmc_sleep_busy_cb, host); + + out_release: + mmc_retune_release(host); +diff --git a/drivers/mmc/core/mmc_ops.c b/drivers/mmc/core/mmc_ops.c +index d63d1c735335c..180d7e9d3400a 100644 +--- a/drivers/mmc/core/mmc_ops.c ++++ b/drivers/mmc/core/mmc_ops.c +@@ -21,6 +21,8 @@ + + #define MMC_BKOPS_TIMEOUT_MS (120 * 1000) /* 120s */ + #define MMC_SANITIZE_TIMEOUT_MS (240 * 1000) /* 240s */ ++#define MMC_OP_COND_PERIOD_US (1 * 1000) /* 1ms */ ++#define MMC_OP_COND_TIMEOUT_MS 1000 /* 1s */ + + static const u8 tuning_blk_pattern_4bit[] = { + 0xff, 0x0f, 0xff, 0x00, 0xff, 0xcc, 0xc3, 0xcc, +@@ -232,7 +234,9 @@ int mmc_send_op_cond(struct mmc_host *host, u32 ocr, u32 *rocr) + cmd.arg = mmc_host_is_spi(host) ? 0 : ocr; + cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R3 | MMC_CMD_BCR; + +- err = __mmc_poll_for_busy(host, 1000, &__mmc_send_op_cond_cb, &cb_data); ++ err = __mmc_poll_for_busy(host, MMC_OP_COND_PERIOD_US, ++ MMC_OP_COND_TIMEOUT_MS, ++ &__mmc_send_op_cond_cb, &cb_data); + if (err) + return err; + +@@ -495,13 +499,14 @@ static int mmc_busy_cb(void *cb_data, bool *busy) + return 0; + } + +-int __mmc_poll_for_busy(struct mmc_host *host, unsigned int timeout_ms, ++int __mmc_poll_for_busy(struct mmc_host *host, unsigned int period_us, ++ unsigned int timeout_ms, + int (*busy_cb)(void *cb_data, bool *busy), + void *cb_data) + { + int err; + unsigned long timeout; +- unsigned int udelay = 32, udelay_max = 32768; ++ unsigned int udelay = period_us ? period_us : 32, udelay_max = 32768; + bool expired = false; + bool busy = false; + +@@ -546,7 +551,7 @@ int mmc_poll_for_busy(struct mmc_card *card, unsigned int timeout_ms, + cb_data.retry_crc_err = retry_crc_err; + cb_data.busy_cmd = busy_cmd; + +- return __mmc_poll_for_busy(host, timeout_ms, &mmc_busy_cb, &cb_data); ++ return __mmc_poll_for_busy(host, 0, timeout_ms, &mmc_busy_cb, &cb_data); + } + EXPORT_SYMBOL_GPL(mmc_poll_for_busy); + +diff --git a/drivers/mmc/core/mmc_ops.h b/drivers/mmc/core/mmc_ops.h +index fd266c7fa41a5..9fc6c320a4620 100644 +--- a/drivers/mmc/core/mmc_ops.h ++++ b/drivers/mmc/core/mmc_ops.h +@@ -42,7 +42,8 @@ int mmc_get_ext_csd(struct mmc_card *card, u8 **new_ext_csd); + int mmc_switch_status(struct mmc_card *card, bool crc_err_fatal); + bool mmc_prepare_busy_cmd(struct mmc_host *host, struct mmc_command *cmd, + unsigned int timeout_ms); +-int __mmc_poll_for_busy(struct mmc_host *host, unsigned int timeout_ms, ++int __mmc_poll_for_busy(struct mmc_host *host, unsigned int period_us, ++ unsigned int timeout_ms, + int (*busy_cb)(void *cb_data, bool *busy), + void *cb_data); + int mmc_poll_for_busy(struct mmc_card *card, unsigned int timeout_ms, +diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c +index 03636a432e2da..c2859ce3f6329 100644 +--- a/drivers/mmc/core/sd.c ++++ b/drivers/mmc/core/sd.c +@@ -1667,7 +1667,7 @@ static int sd_poweroff_notify(struct mmc_card *card) + + cb_data.card = card; + cb_data.reg_buf = reg_buf; +- err = __mmc_poll_for_busy(card->host, SD_POWEROFF_NOTIFY_TIMEOUT_MS, ++ err = __mmc_poll_for_busy(card->host, 0, SD_POWEROFF_NOTIFY_TIMEOUT_MS, + &sd_busy_poweroff_notify_cb, &cb_data); + + out: +-- +2.42.0 + diff --git a/queue-5.15/mptcp-more-conservative-check-for-zero-probes.patch b/queue-5.15/mptcp-more-conservative-check-for-zero-probes.patch new file mode 100644 index 00000000000..0faec632a7f --- /dev/null +++ b/queue-5.15/mptcp-more-conservative-check-for-zero-probes.patch @@ -0,0 +1,98 @@ +From 141c3465d213aff03d860801c1823cc610b5741e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 18 Oct 2023 11:23:54 -0700 +Subject: mptcp: more conservative check for zero probes + +From: Paolo Abeni + +[ Upstream commit 72377ab2d671befd6390a1d5677f5cca61235b65 ] + +Christoph reported that the MPTCP protocol can find the subflow-level +write queue unexpectedly not empty while crafting a zero-window probe, +hitting a warning: + +------------[ cut here ]------------ +WARNING: CPU: 0 PID: 188 at net/mptcp/protocol.c:1312 mptcp_sendmsg_frag+0xc06/0xe70 +Modules linked in: +CPU: 0 PID: 188 Comm: kworker/0:2 Not tainted 6.6.0-rc2-g1176aa719d7a #47 +Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.11.0-2.el7 04/01/2014 +Workqueue: events mptcp_worker +RIP: 0010:mptcp_sendmsg_frag+0xc06/0xe70 net/mptcp/protocol.c:1312 +RAX: 47d0530de347ff6a RBX: 47d0530de347ff6b RCX: ffff8881015d3c00 +RDX: ffff8881015d3c00 RSI: 47d0530de347ff6b RDI: 47d0530de347ff6b +RBP: 47d0530de347ff6b R08: ffffffff8243c6a8 R09: ffffffff82042d9c +R10: 0000000000000002 R11: ffffffff82056850 R12: ffff88812a13d580 +R13: 0000000000000001 R14: ffff88812b375e50 R15: ffff88812bbf3200 +FS: 0000000000000000(0000) GS:ffff88813bc00000(0000) knlGS:0000000000000000 +CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 +CR2: 0000000000695118 CR3: 0000000115dfc001 CR4: 0000000000170ef0 +Call Trace: + + __subflow_push_pending+0xa4/0x420 net/mptcp/protocol.c:1545 + __mptcp_push_pending+0x128/0x3b0 net/mptcp/protocol.c:1614 + mptcp_release_cb+0x218/0x5b0 net/mptcp/protocol.c:3391 + release_sock+0xf6/0x100 net/core/sock.c:3521 + mptcp_worker+0x6e8/0x8f0 net/mptcp/protocol.c:2746 + process_scheduled_works+0x341/0x690 kernel/workqueue.c:2630 + worker_thread+0x3a7/0x610 kernel/workqueue.c:2784 + kthread+0x143/0x180 kernel/kthread.c:388 + ret_from_fork+0x4d/0x60 arch/x86/kernel/process.c:147 + ret_from_fork_asm+0x1b/0x30 arch/x86/entry/entry_64.S:304 + + +The root cause of the issue is that expectations are wrong: e.g. due +to MPTCP-level re-injection we can hit the critical condition. + +Explicitly avoid the zero-window probe when the subflow write queue +is not empty and drop the related warnings. + +Reported-by: Christoph Paasch +Closes: https://github.com/multipath-tcp/mptcp_net-next/issues/444 +Fixes: f70cad1085d1 ("mptcp: stop relying on tcp_tx_skb_cache") +Cc: stable@vger.kernel.org +Reviewed-by: Mat Martineau +Signed-off-by: Paolo Abeni +Signed-off-by: Mat Martineau +Link: https://lore.kernel.org/r/20231018-send-net-20231018-v1-3-17ecb002e41d@kernel.org +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/mptcp/protocol.c | 8 +------- + 1 file changed, 1 insertion(+), 7 deletions(-) + +diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c +index b9613e02e2de1..62e1875b92904 100644 +--- a/net/mptcp/protocol.c ++++ b/net/mptcp/protocol.c +@@ -1337,7 +1337,7 @@ static int mptcp_sendmsg_frag(struct sock *sk, struct sock *ssk, + if (copy == 0) { + u64 snd_una = READ_ONCE(msk->snd_una); + +- if (snd_una != msk->snd_nxt) { ++ if (snd_una != msk->snd_nxt || tcp_write_queue_tail(ssk)) { + tcp_remove_empty_skb(ssk); + return 0; + } +@@ -1345,11 +1345,6 @@ static int mptcp_sendmsg_frag(struct sock *sk, struct sock *ssk, + zero_window_probe = true; + data_seq = snd_una - 1; + copy = 1; +- +- /* all mptcp-level data is acked, no skbs should be present into the +- * ssk write queue +- */ +- WARN_ON_ONCE(reuse_skb); + } + + copy = min_t(size_t, copy, info->limit - info->sent); +@@ -1379,7 +1374,6 @@ static int mptcp_sendmsg_frag(struct sock *sk, struct sock *ssk, + if (reuse_skb) { + TCP_SKB_CB(skb)->tcp_flags &= ~TCPHDR_PSH; + mpext->data_len += copy; +- WARN_ON_ONCE(zero_window_probe); + goto out; + } + +-- +2.42.0 + diff --git a/queue-5.15/pinctrl-qcom-lpass-lpi-fix-concurrent-register-updat.patch b/queue-5.15/pinctrl-qcom-lpass-lpi-fix-concurrent-register-updat.patch new file mode 100644 index 00000000000..09dfaeb0089 --- /dev/null +++ b/queue-5.15/pinctrl-qcom-lpass-lpi-fix-concurrent-register-updat.patch @@ -0,0 +1,124 @@ +From 5f5506a5b7a6ce6c09eeeec81ac326d7cdc8553d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 13 Oct 2023 16:57:05 +0200 +Subject: pinctrl: qcom: lpass-lpi: fix concurrent register updates + +From: Krzysztof Kozlowski + +[ Upstream commit c8befdc411e5fd1bf95a13e8744c8ca79b412bee ] + +The Qualcomm LPASS LPI pin controller driver uses one lock for guarding +Read-Modify-Write code for slew rate registers. However the pin +configuration and muxing registers have exactly the same RMW code but +are not protected. + +Pin controller framework does not provide locking here, thus it is +possible to trigger simultaneous change of pin configuration registers +resulting in non-atomic changes. + +Protect from concurrent access by re-using the same lock used to cover +the slew rate register. Using the same lock instead of adding second +one will make more sense, once we add support for newer Qualcomm SoC, +where slew rate is configured in the same register as pin +configuration/muxing. + +Fixes: 6e261d1090d6 ("pinctrl: qcom: Add sm8250 lpass lpi pinctrl driver") +Cc: stable@vger.kernel.org +Reviewed-by: Linus Walleij +Signed-off-by: Krzysztof Kozlowski +Link: https://lore.kernel.org/r/20231013145705.219954-1-krzysztof.kozlowski@linaro.org +Signed-off-by: Linus Walleij +Signed-off-by: Sasha Levin +--- + drivers/pinctrl/qcom/pinctrl-lpass-lpi.c | 17 +++++++++++------ + 1 file changed, 11 insertions(+), 6 deletions(-) + +diff --git a/drivers/pinctrl/qcom/pinctrl-lpass-lpi.c b/drivers/pinctrl/qcom/pinctrl-lpass-lpi.c +index dd1c9fd733c8f..ec37ad43a6364 100644 +--- a/drivers/pinctrl/qcom/pinctrl-lpass-lpi.c ++++ b/drivers/pinctrl/qcom/pinctrl-lpass-lpi.c +@@ -102,7 +102,8 @@ struct lpi_pinctrl { + char __iomem *tlmm_base; + char __iomem *slew_base; + struct clk_bulk_data clks[MAX_LPI_NUM_CLKS]; +- struct mutex slew_access_lock; ++ /* Protects from concurrent register updates */ ++ struct mutex lock; + const struct lpi_pinctrl_variant_data *data; + }; + +@@ -330,9 +331,11 @@ static int lpi_gpio_set_mux(struct pinctrl_dev *pctldev, unsigned int function, + if (WARN_ON(i == g->nfuncs)) + return -EINVAL; + ++ mutex_lock(&pctrl->lock); + val = lpi_gpio_read(pctrl, pin, LPI_GPIO_CFG_REG); + u32p_replace_bits(&val, i, LPI_GPIO_FUNCTION_MASK); + lpi_gpio_write(pctrl, pin, LPI_GPIO_CFG_REG, val); ++ mutex_unlock(&pctrl->lock); + + return 0; + } +@@ -438,14 +441,14 @@ static int lpi_config_set(struct pinctrl_dev *pctldev, unsigned int group, + if (slew_offset == NO_SLEW) + break; + +- mutex_lock(&pctrl->slew_access_lock); ++ mutex_lock(&pctrl->lock); + + sval = ioread32(pctrl->slew_base + LPI_SLEW_RATE_CTL_REG); + sval &= ~(LPI_SLEW_RATE_MASK << slew_offset); + sval |= arg << slew_offset; + iowrite32(sval, pctrl->slew_base + LPI_SLEW_RATE_CTL_REG); + +- mutex_unlock(&pctrl->slew_access_lock); ++ mutex_unlock(&pctrl->lock); + break; + default: + return -EINVAL; +@@ -461,6 +464,7 @@ static int lpi_config_set(struct pinctrl_dev *pctldev, unsigned int group, + lpi_gpio_write(pctrl, group, LPI_GPIO_VALUE_REG, val); + } + ++ mutex_lock(&pctrl->lock); + val = lpi_gpio_read(pctrl, group, LPI_GPIO_CFG_REG); + + u32p_replace_bits(&val, pullup, LPI_GPIO_PULL_MASK); +@@ -469,6 +473,7 @@ static int lpi_config_set(struct pinctrl_dev *pctldev, unsigned int group, + u32p_replace_bits(&val, output_enabled, LPI_GPIO_OE_MASK); + + lpi_gpio_write(pctrl, group, LPI_GPIO_CFG_REG, val); ++ mutex_unlock(&pctrl->lock); + + return 0; + } +@@ -642,7 +647,7 @@ static int lpi_pinctrl_probe(struct platform_device *pdev) + pctrl->chip.of_gpio_n_cells = 2; + pctrl->chip.can_sleep = false; + +- mutex_init(&pctrl->slew_access_lock); ++ mutex_init(&pctrl->lock); + + pctrl->ctrl = devm_pinctrl_register(dev, &pctrl->desc, pctrl); + if (IS_ERR(pctrl->ctrl)) { +@@ -660,7 +665,7 @@ static int lpi_pinctrl_probe(struct platform_device *pdev) + return 0; + + err_pinctrl: +- mutex_destroy(&pctrl->slew_access_lock); ++ mutex_destroy(&pctrl->lock); + clk_bulk_disable_unprepare(MAX_LPI_NUM_CLKS, pctrl->clks); + + return ret; +@@ -670,7 +675,7 @@ static int lpi_pinctrl_remove(struct platform_device *pdev) + { + struct lpi_pinctrl *pctrl = platform_get_drvdata(pdev); + +- mutex_destroy(&pctrl->slew_access_lock); ++ mutex_destroy(&pctrl->lock); + clk_bulk_disable_unprepare(MAX_LPI_NUM_CLKS, pctrl->clks); + + return 0; +-- +2.42.0 + diff --git a/queue-5.15/series b/queue-5.15/series new file mode 100644 index 00000000000..adb2cef6ae9 --- /dev/null +++ b/queue-5.15/series @@ -0,0 +1,22 @@ +mmc-core-change-__mmc_poll_for_busy-parameter-type.patch +mmc-core-adjust-polling-interval-for-cmd1.patch +mmc-core-restore-almost-the-busy-polling-for-mmc_sen.patch +mmc-core-align-to-common-busy-polling-behaviour-for-.patch +mmc-block-ioctl-do-write-error-check-for-spi.patch +mmc-core-fix-error-propagation-for-some-ioctl-comman.patch +asoc-rt9120-add-rt9210-audio-amplifier-support.patch +asoc-codecs-add-wsa883x-amplifier-support.patch +asoc-rt1318-add-rt1318-sdca-vendor-specific-driver.patch +asoc-codecs-constify-static-sdw_slave_ops-struct.patch +asoc-codecs-wcd938x-fix-accessing-regmap-on-unattach.patch +asoc-codecs-wcd938x-fix-resource-leaks-on-bind-error.patch +asoc-codecs-wcd938x-convert-to-platform-remove-callb.patch +asoc-codecs-wcd938x-simplify-with-dev_err_probe.patch +asoc-codecs-wcd938x-fix-regulator-leaks-on-probe-err.patch +asoc-codecs-wcd938x-fix-runtime-pm-imbalance-on-remo.patch +pinctrl-qcom-lpass-lpi-fix-concurrent-register-updat.patch +tcp-remove-dead-code-from-tcp_sendmsg_locked.patch +tcp-cleanup-tcp_remove_empty_skb-use.patch +mptcp-more-conservative-check-for-zero-probes.patch +mcb-return-actual-parsed-size-when-reading-chameleon.patch +mcb-lpc-reallocate-memory-region-to-avoid-memory-ove.patch diff --git a/queue-5.15/tcp-cleanup-tcp_remove_empty_skb-use.patch b/queue-5.15/tcp-cleanup-tcp_remove_empty_skb-use.patch new file mode 100644 index 00000000000..736795a6d92 --- /dev/null +++ b/queue-5.15/tcp-cleanup-tcp_remove_empty_skb-use.patch @@ -0,0 +1,95 @@ +From a97a36302ef8c48118b1973810eabe8f097822e9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 27 Oct 2021 13:19:18 -0700 +Subject: tcp: cleanup tcp_remove_empty_skb() use + +From: Eric Dumazet + +[ Upstream commit 27728ba80f1eb279b209bbd5922fdeebe52d9e30 ] + +All tcp_remove_empty_skb() callers now use tcp_write_queue_tail() +for the skb argument, we can therefore factorize code. + +Signed-off-by: Eric Dumazet +Signed-off-by: David S. Miller +Stable-dep-of: 72377ab2d671 ("mptcp: more conservative check for zero probes") +Signed-off-by: Sasha Levin +--- + include/net/tcp.h | 2 +- + net/ipv4/tcp.c | 9 +++++---- + net/mptcp/protocol.c | 4 ++-- + 3 files changed, 8 insertions(+), 7 deletions(-) + +diff --git a/include/net/tcp.h b/include/net/tcp.h +index e93a48edf438c..3aee02ad0116b 100644 +--- a/include/net/tcp.h ++++ b/include/net/tcp.h +@@ -314,7 +314,7 @@ void tcp_shutdown(struct sock *sk, int how); + int tcp_v4_early_demux(struct sk_buff *skb); + int tcp_v4_rcv(struct sk_buff *skb); + +-void tcp_remove_empty_skb(struct sock *sk, struct sk_buff *skb); ++void tcp_remove_empty_skb(struct sock *sk); + int tcp_v4_tw_remember_stamp(struct inet_timewait_sock *tw); + int tcp_sendmsg(struct sock *sk, struct msghdr *msg, size_t size); + int tcp_sendmsg_locked(struct sock *sk, struct msghdr *msg, size_t size); +diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c +index 2115a0e5c98f7..6dcb77a2bde60 100644 +--- a/net/ipv4/tcp.c ++++ b/net/ipv4/tcp.c +@@ -953,8 +953,10 @@ int tcp_send_mss(struct sock *sk, int *size_goal, int flags) + * importantly be able to generate EPOLLOUT for Edge Trigger epoll() + * users. + */ +-void tcp_remove_empty_skb(struct sock *sk, struct sk_buff *skb) ++void tcp_remove_empty_skb(struct sock *sk) + { ++ struct sk_buff *skb = tcp_write_queue_tail(sk); ++ + if (skb && TCP_SKB_CB(skb)->seq == TCP_SKB_CB(skb)->end_seq) { + tcp_unlink_write_queue(skb, sk); + if (tcp_write_queue_empty(sk)) +@@ -1107,7 +1109,7 @@ ssize_t do_tcp_sendpages(struct sock *sk, struct page *page, int offset, + return copied; + + do_error: +- tcp_remove_empty_skb(sk, tcp_write_queue_tail(sk)); ++ tcp_remove_empty_skb(sk); + if (copied) + goto out; + out_err: +@@ -1429,8 +1431,7 @@ int tcp_sendmsg_locked(struct sock *sk, struct msghdr *msg, size_t size) + return copied + copied_syn; + + do_error: +- skb = tcp_write_queue_tail(sk); +- tcp_remove_empty_skb(sk, skb); ++ tcp_remove_empty_skb(sk); + + if (copied + copied_syn) + goto out; +diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c +index 82b1583f709d3..b9613e02e2de1 100644 +--- a/net/mptcp/protocol.c ++++ b/net/mptcp/protocol.c +@@ -1338,7 +1338,7 @@ static int mptcp_sendmsg_frag(struct sock *sk, struct sock *ssk, + u64 snd_una = READ_ONCE(msk->snd_una); + + if (snd_una != msk->snd_nxt) { +- tcp_remove_empty_skb(ssk, tcp_write_queue_tail(ssk)); ++ tcp_remove_empty_skb(ssk); + return 0; + } + +@@ -1354,7 +1354,7 @@ static int mptcp_sendmsg_frag(struct sock *sk, struct sock *ssk, + + copy = min_t(size_t, copy, info->limit - info->sent); + if (!sk_wmem_schedule(ssk, copy)) { +- tcp_remove_empty_skb(ssk, tcp_write_queue_tail(ssk)); ++ tcp_remove_empty_skb(ssk); + return -ENOMEM; + } + +-- +2.42.0 + diff --git a/queue-5.15/tcp-remove-dead-code-from-tcp_sendmsg_locked.patch b/queue-5.15/tcp-remove-dead-code-from-tcp_sendmsg_locked.patch new file mode 100644 index 00000000000..4dbddaffe93 --- /dev/null +++ b/queue-5.15/tcp-remove-dead-code-from-tcp_sendmsg_locked.patch @@ -0,0 +1,51 @@ +From 91a98ca6eaaa2065d80085257a52506d8a36f9e5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 27 Oct 2021 13:19:17 -0700 +Subject: tcp: remove dead code from tcp_sendmsg_locked() + +From: Eric Dumazet + +[ Upstream commit 3ded97bc41a1e76e1e72eeb192331c01ceacc4bc ] + +TCP sendmsg() no longer puts payload in skb head, we can remove +dead code. + +Signed-off-by: Eric Dumazet +Signed-off-by: David S. Miller +Stable-dep-of: 72377ab2d671 ("mptcp: more conservative check for zero probes") +Signed-off-by: Sasha Levin +--- + net/ipv4/tcp.c | 10 +--------- + 1 file changed, 1 insertion(+), 9 deletions(-) + +diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c +index a91cf000bb61b..2115a0e5c98f7 100644 +--- a/net/ipv4/tcp.c ++++ b/net/ipv4/tcp.c +@@ -1330,14 +1330,7 @@ int tcp_sendmsg_locked(struct sock *sk, struct msghdr *msg, size_t size) + if (copy > msg_data_left(msg)) + copy = msg_data_left(msg); + +- /* Where to copy to? */ +- if (skb_availroom(skb) > 0 && !zc) { +- /* We have some space in skb head. Superb! */ +- copy = min_t(int, copy, skb_availroom(skb)); +- err = skb_add_data_nocache(sk, skb, &msg->msg_iter, copy); +- if (err) +- goto do_fault; +- } else if (!zc) { ++ if (!zc) { + bool merge = true; + int i = skb_shinfo(skb)->nr_frags; + struct page_frag *pfrag = sk_page_frag(sk); +@@ -1437,7 +1430,6 @@ int tcp_sendmsg_locked(struct sock *sk, struct msghdr *msg, size_t size) + + do_error: + skb = tcp_write_queue_tail(sk); +-do_fault: + tcp_remove_empty_skb(sk, skb); + + if (copied + copied_syn) +-- +2.42.0 +