// 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 #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_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, }; static const char * const wsa_dev_mode_text[] = { "Speaker", "Receiver", "Ultrasound" }; enum { SPEAKER, RECEIVER, ULTRASOUND, }; static const struct soc_enum wsa_dev_mode_enum = SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(wsa_dev_mode_text), wsa_dev_mode_text); /* 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 const 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_MAPLE, .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, .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 const struct sdw_slave_ops wsa883x_slave_ops = { .update_status = wsa883x_update_status, .port_prep = wsa883x_port_prep, }; static int wsa_dev_mode_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); struct wsa883x_priv *wsa883x = snd_soc_component_get_drvdata(component); ucontrol->value.enumerated.item[0] = wsa883x->dev_mode; return 0; } static int wsa_dev_mode_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); struct wsa883x_priv *wsa883x = snd_soc_component_get_drvdata(component); if (wsa883x->dev_mode == ucontrol->value.enumerated.item[0]) return 0; wsa883x->dev_mode = ucontrol->value.enumerated.item[0]; return 1; } static const SNDRV_CTL_TLVD_DECLARE_DB_RANGE(pa_gain, 0, 14, TLV_DB_SCALE_ITEM(-300, 0, 0), 15, 29, TLV_DB_SCALE_ITEM(-300, 150, 0), 30, 31, TLV_DB_SCALE_ITEM(1800, 0, 0), ); static int wsa883x_get_swr_port(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_soc_component *comp = snd_soc_kcontrol_component(kcontrol); struct wsa883x_priv *data = snd_soc_component_get_drvdata(comp); struct soc_mixer_control *mixer = (struct soc_mixer_control *)kcontrol->private_value; int portidx = mixer->reg; ucontrol->value.integer.value[0] = data->port_enable[portidx]; return 0; } static int wsa883x_set_swr_port(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_soc_component *comp = snd_soc_kcontrol_component(kcontrol); struct wsa883x_priv *data = snd_soc_component_get_drvdata(comp); struct soc_mixer_control *mixer = (struct soc_mixer_control *)kcontrol->private_value; int portidx = mixer->reg; if (ucontrol->value.integer.value[0]) { if (data->port_enable[portidx]) return 0; data->port_enable[portidx] = true; } else { if (!data->port_enable[portidx]) return 0; data->port_enable[portidx] = false; } return 1; } static int wsa883x_get_comp_offset(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); struct wsa883x_priv *wsa883x = snd_soc_component_get_drvdata(component); ucontrol->value.integer.value[0] = wsa883x->comp_offset; return 0; } static int wsa883x_set_comp_offset(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); struct wsa883x_priv *wsa883x = snd_soc_component_get_drvdata(component); if (wsa883x->comp_offset == ucontrol->value.integer.value[0]) return 0; wsa883x->comp_offset = ucontrol->value.integer.value[0]; return 1; } 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 int wsa883x_spkr_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 wsa883x_priv *wsa883x = snd_soc_component_get_drvdata(component); switch (event) { case SND_SOC_DAPM_POST_PMU: switch (wsa883x->dev_mode) { case RECEIVER: snd_soc_component_write_field(component, WSA883X_CDC_PATH_MODE, WSA883X_RXD_MODE_MASK, WSA883X_RXD_MODE_HIFI); snd_soc_component_write_field(component, WSA883X_SPKR_PWM_CLK_CTL, WSA883X_SPKR_PWM_FREQ_SEL_MASK, WSA883X_SPKR_PWM_FREQ_F600KHZ); snd_soc_component_write_field(component, WSA883X_DRE_CTL_0, WSA883X_DRE_PROG_DELAY_MASK, 0x0); break; case SPEAKER: snd_soc_component_write_field(component, WSA883X_CDC_PATH_MODE, WSA883X_RXD_MODE_MASK, WSA883X_RXD_MODE_NORMAL); snd_soc_component_write_field(component, WSA883X_SPKR_PWM_CLK_CTL, WSA883X_SPKR_PWM_FREQ_SEL_MASK, WSA883X_SPKR_PWM_FREQ_F300KHZ); snd_soc_component_write_field(component, WSA883X_DRE_CTL_0, WSA883X_DRE_PROG_DELAY_MASK, 0x9); break; default: break; } if (wsa883x->port_enable[WSA883X_PORT_COMP]) snd_soc_component_write_field(component, WSA883X_DRE_CTL_0, WSA883X_DRE_OFFSET_MASK, wsa883x->comp_offset); snd_soc_component_write_field(component, WSA883X_VBAT_ADC_FLT_CTL, WSA883X_VBAT_ADC_COEF_SEL_MASK, WSA883X_VBAT_ADC_COEF_F_1DIV16); snd_soc_component_write_field(component, WSA883X_VBAT_ADC_FLT_CTL, WSA883X_VBAT_ADC_FLT_EN_MASK, 0x1); snd_soc_component_write_field(component, WSA883X_PDM_WD_CTL, WSA883X_PDM_EN_MASK, WSA883X_PDM_ENABLE); break; case SND_SOC_DAPM_PRE_PMD: snd_soc_component_write_field(component, WSA883X_VBAT_ADC_FLT_CTL, WSA883X_VBAT_ADC_FLT_EN_MASK, 0x0); snd_soc_component_write_field(component, WSA883X_VBAT_ADC_FLT_CTL, WSA883X_VBAT_ADC_COEF_SEL_MASK, WSA883X_VBAT_ADC_COEF_F_1DIV2); snd_soc_component_write_field(component, WSA883X_PA_FSM_CTL, WSA883X_GLOBAL_PA_EN_MASK, 0); snd_soc_component_write_field(component, WSA883X_PDM_WD_CTL, WSA883X_PDM_EN_MASK, 0); break; } return 0; } static const struct snd_soc_dapm_widget wsa883x_dapm_widgets[] = { SND_SOC_DAPM_INPUT("IN"), SND_SOC_DAPM_SPK("SPKR", wsa883x_spkr_event), }; static const struct snd_kcontrol_new wsa883x_snd_controls[] = { SOC_SINGLE_RANGE_TLV("PA Volume", WSA883X_DRE_CTL_1, 1, 0x0, 0x1f, 1, pa_gain), SOC_ENUM_EXT("WSA MODE", wsa_dev_mode_enum, wsa_dev_mode_get, wsa_dev_mode_put), SOC_SINGLE_EXT("COMP Offset", SND_SOC_NOPM, 0, 4, 0, wsa883x_get_comp_offset, wsa883x_set_comp_offset), SOC_SINGLE_EXT("DAC Switch", WSA883X_PORT_DAC, 0, 1, 0, wsa883x_get_swr_port, wsa883x_set_swr_port), SOC_SINGLE_EXT("COMP Switch", WSA883X_PORT_COMP, 0, 1, 0, wsa883x_get_swr_port, wsa883x_set_swr_port), SOC_SINGLE_EXT("BOOST Switch", WSA883X_PORT_BOOST, 0, 1, 0, wsa883x_get_swr_port, wsa883x_set_swr_port), SOC_SINGLE_EXT("VISENSE Switch", WSA883X_PORT_VISENSE, 0, 1, 0, wsa883x_get_swr_port, wsa883x_set_swr_port), }; static const struct snd_soc_dapm_route wsa883x_audio_map[] = { {"SPKR", NULL, "IN"}, }; static const struct snd_soc_component_driver wsa883x_component_drv = { .name = "WSA883x", .probe = wsa883x_codec_probe, .controls = wsa883x_snd_controls, .num_controls = ARRAY_SIZE(wsa883x_snd_controls), .dapm_widgets = wsa883x_dapm_widgets, .num_dapm_widgets = ARRAY_SIZE(wsa883x_dapm_widgets), .dapm_routes = wsa883x_audio_map, .num_dapm_routes = ARRAY_SIZE(wsa883x_audio_map), }; 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, WSA883X_GLOBAL_PA_ENABLE); } 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, .mute_unmute_on_trigger = true, }; 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_min = 8000, .rate_max = 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(dev, sizeof(*wsa883x), GFP_KERNEL); if (!wsa883x) return -ENOMEM; wsa883x->vdd = devm_regulator_get(dev, "vdd"); if (IS_ERR(wsa883x->vdd)) return dev_err_probe(dev, PTR_ERR(wsa883x->vdd), "No vdd regulator found\n"); ret = regulator_enable(wsa883x->vdd); if (ret) return dev_err_probe(dev, ret, "Failed to enable vdd regulator\n"); wsa883x->sd_n = devm_gpiod_get_optional(dev, "powerdown", GPIOD_FLAGS_BIT_NONEXCLUSIVE | GPIOD_OUT_HIGH); if (IS_ERR(wsa883x->sd_n)) { ret = dev_err_probe(dev, PTR_ERR(wsa883x->sd_n), "Shutdown Control GPIO not found\n"); goto err; } dev_set_drvdata(dev, wsa883x); wsa883x->slave = pdev; wsa883x->dev = 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.simple_clk_stop_capable = true; 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, 0); wsa883x->regmap = devm_regmap_init_sdw(pdev, &wsa883x_regmap_config); if (IS_ERR(wsa883x->regmap)) { gpiod_direction_output(wsa883x->sd_n, 1); ret = dev_err_probe(dev, PTR_ERR(wsa883x->regmap), "regmap_init failed\n"); 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(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); regcache_cache_only(regmap, true); regcache_mark_dirty(regmap); return 0; } static int __maybe_unused wsa883x_runtime_resume(struct device *dev) { struct regmap *regmap = dev_get_regmap(dev, NULL); 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), {}, }; MODULE_DEVICE_TABLE(sdw, wsa883x_swr_id); 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");