1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun // Copyright (c) 2015-2017, The Linux Foundation.
3*4882a593Smuzhiyun // Copyright (c) 2019, Linaro Limited
4*4882a593Smuzhiyun
5*4882a593Smuzhiyun #include <linux/bitops.h>
6*4882a593Smuzhiyun #include <linux/gpio.h>
7*4882a593Smuzhiyun #include <linux/gpio/consumer.h>
8*4882a593Smuzhiyun #include <linux/interrupt.h>
9*4882a593Smuzhiyun #include <linux/module.h>
10*4882a593Smuzhiyun #include <linux/of.h>
11*4882a593Smuzhiyun #include <linux/of_gpio.h>
12*4882a593Smuzhiyun #include <linux/regmap.h>
13*4882a593Smuzhiyun #include <linux/slab.h>
14*4882a593Smuzhiyun #include <linux/soundwire/sdw.h>
15*4882a593Smuzhiyun #include <linux/soundwire/sdw_registers.h>
16*4882a593Smuzhiyun #include <linux/soundwire/sdw_type.h>
17*4882a593Smuzhiyun #include <sound/soc.h>
18*4882a593Smuzhiyun #include <sound/tlv.h>
19*4882a593Smuzhiyun
20*4882a593Smuzhiyun #define WSA881X_DIGITAL_BASE 0x3000
21*4882a593Smuzhiyun #define WSA881X_ANALOG_BASE 0x3100
22*4882a593Smuzhiyun
23*4882a593Smuzhiyun /* Digital register address space */
24*4882a593Smuzhiyun #define WSA881X_CHIP_ID0 (WSA881X_DIGITAL_BASE + 0x0000)
25*4882a593Smuzhiyun #define WSA881X_CHIP_ID1 (WSA881X_DIGITAL_BASE + 0x0001)
26*4882a593Smuzhiyun #define WSA881X_CHIP_ID2 (WSA881X_DIGITAL_BASE + 0x0002)
27*4882a593Smuzhiyun #define WSA881X_CHIP_ID3 (WSA881X_DIGITAL_BASE + 0x0003)
28*4882a593Smuzhiyun #define WSA881X_BUS_ID (WSA881X_DIGITAL_BASE + 0x0004)
29*4882a593Smuzhiyun #define WSA881X_CDC_RST_CTL (WSA881X_DIGITAL_BASE + 0x0005)
30*4882a593Smuzhiyun #define WSA881X_CDC_TOP_CLK_CTL (WSA881X_DIGITAL_BASE + 0x0006)
31*4882a593Smuzhiyun #define WSA881X_CDC_ANA_CLK_CTL (WSA881X_DIGITAL_BASE + 0x0007)
32*4882a593Smuzhiyun #define WSA881X_CDC_DIG_CLK_CTL (WSA881X_DIGITAL_BASE + 0x0008)
33*4882a593Smuzhiyun #define WSA881X_CLOCK_CONFIG (WSA881X_DIGITAL_BASE + 0x0009)
34*4882a593Smuzhiyun #define WSA881X_ANA_CTL (WSA881X_DIGITAL_BASE + 0x000A)
35*4882a593Smuzhiyun #define WSA881X_SWR_RESET_EN (WSA881X_DIGITAL_BASE + 0x000B)
36*4882a593Smuzhiyun #define WSA881X_RESET_CTL (WSA881X_DIGITAL_BASE + 0x000C)
37*4882a593Smuzhiyun #define WSA881X_TADC_VALUE_CTL (WSA881X_DIGITAL_BASE + 0x000F)
38*4882a593Smuzhiyun #define WSA881X_TEMP_DETECT_CTL (WSA881X_DIGITAL_BASE + 0x0010)
39*4882a593Smuzhiyun #define WSA881X_TEMP_MSB (WSA881X_DIGITAL_BASE + 0x0011)
40*4882a593Smuzhiyun #define WSA881X_TEMP_LSB (WSA881X_DIGITAL_BASE + 0x0012)
41*4882a593Smuzhiyun #define WSA881X_TEMP_CONFIG0 (WSA881X_DIGITAL_BASE + 0x0013)
42*4882a593Smuzhiyun #define WSA881X_TEMP_CONFIG1 (WSA881X_DIGITAL_BASE + 0x0014)
43*4882a593Smuzhiyun #define WSA881X_CDC_CLIP_CTL (WSA881X_DIGITAL_BASE + 0x0015)
44*4882a593Smuzhiyun #define WSA881X_SDM_PDM9_LSB (WSA881X_DIGITAL_BASE + 0x0016)
45*4882a593Smuzhiyun #define WSA881X_SDM_PDM9_MSB (WSA881X_DIGITAL_BASE + 0x0017)
46*4882a593Smuzhiyun #define WSA881X_CDC_RX_CTL (WSA881X_DIGITAL_BASE + 0x0018)
47*4882a593Smuzhiyun #define WSA881X_DEM_BYPASS_DATA0 (WSA881X_DIGITAL_BASE + 0x0019)
48*4882a593Smuzhiyun #define WSA881X_DEM_BYPASS_DATA1 (WSA881X_DIGITAL_BASE + 0x001A)
49*4882a593Smuzhiyun #define WSA881X_DEM_BYPASS_DATA2 (WSA881X_DIGITAL_BASE + 0x001B)
50*4882a593Smuzhiyun #define WSA881X_DEM_BYPASS_DATA3 (WSA881X_DIGITAL_BASE + 0x001C)
51*4882a593Smuzhiyun #define WSA881X_OTP_CTRL0 (WSA881X_DIGITAL_BASE + 0x001D)
52*4882a593Smuzhiyun #define WSA881X_OTP_CTRL1 (WSA881X_DIGITAL_BASE + 0x001E)
53*4882a593Smuzhiyun #define WSA881X_HDRIVE_CTL_GROUP1 (WSA881X_DIGITAL_BASE + 0x001F)
54*4882a593Smuzhiyun #define WSA881X_INTR_MODE (WSA881X_DIGITAL_BASE + 0x0020)
55*4882a593Smuzhiyun #define WSA881X_INTR_MASK (WSA881X_DIGITAL_BASE + 0x0021)
56*4882a593Smuzhiyun #define WSA881X_INTR_STATUS (WSA881X_DIGITAL_BASE + 0x0022)
57*4882a593Smuzhiyun #define WSA881X_INTR_CLEAR (WSA881X_DIGITAL_BASE + 0x0023)
58*4882a593Smuzhiyun #define WSA881X_INTR_LEVEL (WSA881X_DIGITAL_BASE + 0x0024)
59*4882a593Smuzhiyun #define WSA881X_INTR_SET (WSA881X_DIGITAL_BASE + 0x0025)
60*4882a593Smuzhiyun #define WSA881X_INTR_TEST (WSA881X_DIGITAL_BASE + 0x0026)
61*4882a593Smuzhiyun #define WSA881X_PDM_TEST_MODE (WSA881X_DIGITAL_BASE + 0x0030)
62*4882a593Smuzhiyun #define WSA881X_ATE_TEST_MODE (WSA881X_DIGITAL_BASE + 0x0031)
63*4882a593Smuzhiyun #define WSA881X_PIN_CTL_MODE (WSA881X_DIGITAL_BASE + 0x0032)
64*4882a593Smuzhiyun #define WSA881X_PIN_CTL_OE (WSA881X_DIGITAL_BASE + 0x0033)
65*4882a593Smuzhiyun #define WSA881X_PIN_WDATA_IOPAD (WSA881X_DIGITAL_BASE + 0x0034)
66*4882a593Smuzhiyun #define WSA881X_PIN_STATUS (WSA881X_DIGITAL_BASE + 0x0035)
67*4882a593Smuzhiyun #define WSA881X_DIG_DEBUG_MODE (WSA881X_DIGITAL_BASE + 0x0037)
68*4882a593Smuzhiyun #define WSA881X_DIG_DEBUG_SEL (WSA881X_DIGITAL_BASE + 0x0038)
69*4882a593Smuzhiyun #define WSA881X_DIG_DEBUG_EN (WSA881X_DIGITAL_BASE + 0x0039)
70*4882a593Smuzhiyun #define WSA881X_SWR_HM_TEST1 (WSA881X_DIGITAL_BASE + 0x003B)
71*4882a593Smuzhiyun #define WSA881X_SWR_HM_TEST2 (WSA881X_DIGITAL_BASE + 0x003C)
72*4882a593Smuzhiyun #define WSA881X_TEMP_DETECT_DBG_CTL (WSA881X_DIGITAL_BASE + 0x003D)
73*4882a593Smuzhiyun #define WSA881X_TEMP_DEBUG_MSB (WSA881X_DIGITAL_BASE + 0x003E)
74*4882a593Smuzhiyun #define WSA881X_TEMP_DEBUG_LSB (WSA881X_DIGITAL_BASE + 0x003F)
75*4882a593Smuzhiyun #define WSA881X_SAMPLE_EDGE_SEL (WSA881X_DIGITAL_BASE + 0x0044)
76*4882a593Smuzhiyun #define WSA881X_IOPAD_CTL (WSA881X_DIGITAL_BASE + 0x0045)
77*4882a593Smuzhiyun #define WSA881X_SPARE_0 (WSA881X_DIGITAL_BASE + 0x0050)
78*4882a593Smuzhiyun #define WSA881X_SPARE_1 (WSA881X_DIGITAL_BASE + 0x0051)
79*4882a593Smuzhiyun #define WSA881X_SPARE_2 (WSA881X_DIGITAL_BASE + 0x0052)
80*4882a593Smuzhiyun #define WSA881X_OTP_REG_0 (WSA881X_DIGITAL_BASE + 0x0080)
81*4882a593Smuzhiyun #define WSA881X_OTP_REG_1 (WSA881X_DIGITAL_BASE + 0x0081)
82*4882a593Smuzhiyun #define WSA881X_OTP_REG_2 (WSA881X_DIGITAL_BASE + 0x0082)
83*4882a593Smuzhiyun #define WSA881X_OTP_REG_3 (WSA881X_DIGITAL_BASE + 0x0083)
84*4882a593Smuzhiyun #define WSA881X_OTP_REG_4 (WSA881X_DIGITAL_BASE + 0x0084)
85*4882a593Smuzhiyun #define WSA881X_OTP_REG_5 (WSA881X_DIGITAL_BASE + 0x0085)
86*4882a593Smuzhiyun #define WSA881X_OTP_REG_6 (WSA881X_DIGITAL_BASE + 0x0086)
87*4882a593Smuzhiyun #define WSA881X_OTP_REG_7 (WSA881X_DIGITAL_BASE + 0x0087)
88*4882a593Smuzhiyun #define WSA881X_OTP_REG_8 (WSA881X_DIGITAL_BASE + 0x0088)
89*4882a593Smuzhiyun #define WSA881X_OTP_REG_9 (WSA881X_DIGITAL_BASE + 0x0089)
90*4882a593Smuzhiyun #define WSA881X_OTP_REG_10 (WSA881X_DIGITAL_BASE + 0x008A)
91*4882a593Smuzhiyun #define WSA881X_OTP_REG_11 (WSA881X_DIGITAL_BASE + 0x008B)
92*4882a593Smuzhiyun #define WSA881X_OTP_REG_12 (WSA881X_DIGITAL_BASE + 0x008C)
93*4882a593Smuzhiyun #define WSA881X_OTP_REG_13 (WSA881X_DIGITAL_BASE + 0x008D)
94*4882a593Smuzhiyun #define WSA881X_OTP_REG_14 (WSA881X_DIGITAL_BASE + 0x008E)
95*4882a593Smuzhiyun #define WSA881X_OTP_REG_15 (WSA881X_DIGITAL_BASE + 0x008F)
96*4882a593Smuzhiyun #define WSA881X_OTP_REG_16 (WSA881X_DIGITAL_BASE + 0x0090)
97*4882a593Smuzhiyun #define WSA881X_OTP_REG_17 (WSA881X_DIGITAL_BASE + 0x0091)
98*4882a593Smuzhiyun #define WSA881X_OTP_REG_18 (WSA881X_DIGITAL_BASE + 0x0092)
99*4882a593Smuzhiyun #define WSA881X_OTP_REG_19 (WSA881X_DIGITAL_BASE + 0x0093)
100*4882a593Smuzhiyun #define WSA881X_OTP_REG_20 (WSA881X_DIGITAL_BASE + 0x0094)
101*4882a593Smuzhiyun #define WSA881X_OTP_REG_21 (WSA881X_DIGITAL_BASE + 0x0095)
102*4882a593Smuzhiyun #define WSA881X_OTP_REG_22 (WSA881X_DIGITAL_BASE + 0x0096)
103*4882a593Smuzhiyun #define WSA881X_OTP_REG_23 (WSA881X_DIGITAL_BASE + 0x0097)
104*4882a593Smuzhiyun #define WSA881X_OTP_REG_24 (WSA881X_DIGITAL_BASE + 0x0098)
105*4882a593Smuzhiyun #define WSA881X_OTP_REG_25 (WSA881X_DIGITAL_BASE + 0x0099)
106*4882a593Smuzhiyun #define WSA881X_OTP_REG_26 (WSA881X_DIGITAL_BASE + 0x009A)
107*4882a593Smuzhiyun #define WSA881X_OTP_REG_27 (WSA881X_DIGITAL_BASE + 0x009B)
108*4882a593Smuzhiyun #define WSA881X_OTP_REG_28 (WSA881X_DIGITAL_BASE + 0x009C)
109*4882a593Smuzhiyun #define WSA881X_OTP_REG_29 (WSA881X_DIGITAL_BASE + 0x009D)
110*4882a593Smuzhiyun #define WSA881X_OTP_REG_30 (WSA881X_DIGITAL_BASE + 0x009E)
111*4882a593Smuzhiyun #define WSA881X_OTP_REG_31 (WSA881X_DIGITAL_BASE + 0x009F)
112*4882a593Smuzhiyun #define WSA881X_OTP_REG_63 (WSA881X_DIGITAL_BASE + 0x00BF)
113*4882a593Smuzhiyun
114*4882a593Smuzhiyun /* Analog Register address space */
115*4882a593Smuzhiyun #define WSA881X_BIAS_REF_CTRL (WSA881X_ANALOG_BASE + 0x0000)
116*4882a593Smuzhiyun #define WSA881X_BIAS_TEST (WSA881X_ANALOG_BASE + 0x0001)
117*4882a593Smuzhiyun #define WSA881X_BIAS_BIAS (WSA881X_ANALOG_BASE + 0x0002)
118*4882a593Smuzhiyun #define WSA881X_TEMP_OP (WSA881X_ANALOG_BASE + 0x0003)
119*4882a593Smuzhiyun #define WSA881X_TEMP_IREF_CTRL (WSA881X_ANALOG_BASE + 0x0004)
120*4882a593Smuzhiyun #define WSA881X_TEMP_ISENS_CTRL (WSA881X_ANALOG_BASE + 0x0005)
121*4882a593Smuzhiyun #define WSA881X_TEMP_CLK_CTRL (WSA881X_ANALOG_BASE + 0x0006)
122*4882a593Smuzhiyun #define WSA881X_TEMP_TEST (WSA881X_ANALOG_BASE + 0x0007)
123*4882a593Smuzhiyun #define WSA881X_TEMP_BIAS (WSA881X_ANALOG_BASE + 0x0008)
124*4882a593Smuzhiyun #define WSA881X_TEMP_ADC_CTRL (WSA881X_ANALOG_BASE + 0x0009)
125*4882a593Smuzhiyun #define WSA881X_TEMP_DOUT_MSB (WSA881X_ANALOG_BASE + 0x000A)
126*4882a593Smuzhiyun #define WSA881X_TEMP_DOUT_LSB (WSA881X_ANALOG_BASE + 0x000B)
127*4882a593Smuzhiyun #define WSA881X_ADC_EN_MODU_V (WSA881X_ANALOG_BASE + 0x0010)
128*4882a593Smuzhiyun #define WSA881X_ADC_EN_MODU_I (WSA881X_ANALOG_BASE + 0x0011)
129*4882a593Smuzhiyun #define WSA881X_ADC_EN_DET_TEST_V (WSA881X_ANALOG_BASE + 0x0012)
130*4882a593Smuzhiyun #define WSA881X_ADC_EN_DET_TEST_I (WSA881X_ANALOG_BASE + 0x0013)
131*4882a593Smuzhiyun #define WSA881X_ADC_SEL_IBIAS (WSA881X_ANALOG_BASE + 0x0014)
132*4882a593Smuzhiyun #define WSA881X_ADC_EN_SEL_IBAIS (WSA881X_ANALOG_BASE + 0x0015)
133*4882a593Smuzhiyun #define WSA881X_SPKR_DRV_EN (WSA881X_ANALOG_BASE + 0x001A)
134*4882a593Smuzhiyun #define WSA881X_SPKR_DRV_GAIN (WSA881X_ANALOG_BASE + 0x001B)
135*4882a593Smuzhiyun #define WSA881X_PA_GAIN_SEL_MASK BIT(3)
136*4882a593Smuzhiyun #define WSA881X_PA_GAIN_SEL_REG BIT(3)
137*4882a593Smuzhiyun #define WSA881X_PA_GAIN_SEL_DRE 0
138*4882a593Smuzhiyun #define WSA881X_SPKR_PAG_GAIN_MASK GENMASK(7, 4)
139*4882a593Smuzhiyun #define WSA881X_SPKR_DAC_CTL (WSA881X_ANALOG_BASE + 0x001C)
140*4882a593Smuzhiyun #define WSA881X_SPKR_DRV_DBG (WSA881X_ANALOG_BASE + 0x001D)
141*4882a593Smuzhiyun #define WSA881X_SPKR_PWRSTG_DBG (WSA881X_ANALOG_BASE + 0x001E)
142*4882a593Smuzhiyun #define WSA881X_SPKR_OCP_CTL (WSA881X_ANALOG_BASE + 0x001F)
143*4882a593Smuzhiyun #define WSA881X_SPKR_OCP_MASK GENMASK(7, 6)
144*4882a593Smuzhiyun #define WSA881X_SPKR_OCP_EN BIT(7)
145*4882a593Smuzhiyun #define WSA881X_SPKR_OCP_HOLD BIT(6)
146*4882a593Smuzhiyun #define WSA881X_SPKR_CLIP_CTL (WSA881X_ANALOG_BASE + 0x0020)
147*4882a593Smuzhiyun #define WSA881X_SPKR_BBM_CTL (WSA881X_ANALOG_BASE + 0x0021)
148*4882a593Smuzhiyun #define WSA881X_SPKR_MISC_CTL1 (WSA881X_ANALOG_BASE + 0x0022)
149*4882a593Smuzhiyun #define WSA881X_SPKR_MISC_CTL2 (WSA881X_ANALOG_BASE + 0x0023)
150*4882a593Smuzhiyun #define WSA881X_SPKR_BIAS_INT (WSA881X_ANALOG_BASE + 0x0024)
151*4882a593Smuzhiyun #define WSA881X_SPKR_PA_INT (WSA881X_ANALOG_BASE + 0x0025)
152*4882a593Smuzhiyun #define WSA881X_SPKR_BIAS_CAL (WSA881X_ANALOG_BASE + 0x0026)
153*4882a593Smuzhiyun #define WSA881X_SPKR_BIAS_PSRR (WSA881X_ANALOG_BASE + 0x0027)
154*4882a593Smuzhiyun #define WSA881X_SPKR_STATUS1 (WSA881X_ANALOG_BASE + 0x0028)
155*4882a593Smuzhiyun #define WSA881X_SPKR_STATUS2 (WSA881X_ANALOG_BASE + 0x0029)
156*4882a593Smuzhiyun #define WSA881X_BOOST_EN_CTL (WSA881X_ANALOG_BASE + 0x002A)
157*4882a593Smuzhiyun #define WSA881X_BOOST_EN_MASK BIT(7)
158*4882a593Smuzhiyun #define WSA881X_BOOST_EN BIT(7)
159*4882a593Smuzhiyun #define WSA881X_BOOST_CURRENT_LIMIT (WSA881X_ANALOG_BASE + 0x002B)
160*4882a593Smuzhiyun #define WSA881X_BOOST_PS_CTL (WSA881X_ANALOG_BASE + 0x002C)
161*4882a593Smuzhiyun #define WSA881X_BOOST_PRESET_OUT1 (WSA881X_ANALOG_BASE + 0x002D)
162*4882a593Smuzhiyun #define WSA881X_BOOST_PRESET_OUT2 (WSA881X_ANALOG_BASE + 0x002E)
163*4882a593Smuzhiyun #define WSA881X_BOOST_FORCE_OUT (WSA881X_ANALOG_BASE + 0x002F)
164*4882a593Smuzhiyun #define WSA881X_BOOST_LDO_PROG (WSA881X_ANALOG_BASE + 0x0030)
165*4882a593Smuzhiyun #define WSA881X_BOOST_SLOPE_COMP_ISENSE_FB (WSA881X_ANALOG_BASE + 0x0031)
166*4882a593Smuzhiyun #define WSA881X_BOOST_RON_CTL (WSA881X_ANALOG_BASE + 0x0032)
167*4882a593Smuzhiyun #define WSA881X_BOOST_LOOP_STABILITY (WSA881X_ANALOG_BASE + 0x0033)
168*4882a593Smuzhiyun #define WSA881X_BOOST_ZX_CTL (WSA881X_ANALOG_BASE + 0x0034)
169*4882a593Smuzhiyun #define WSA881X_BOOST_START_CTL (WSA881X_ANALOG_BASE + 0x0035)
170*4882a593Smuzhiyun #define WSA881X_BOOST_MISC1_CTL (WSA881X_ANALOG_BASE + 0x0036)
171*4882a593Smuzhiyun #define WSA881X_BOOST_MISC2_CTL (WSA881X_ANALOG_BASE + 0x0037)
172*4882a593Smuzhiyun #define WSA881X_BOOST_MISC3_CTL (WSA881X_ANALOG_BASE + 0x0038)
173*4882a593Smuzhiyun #define WSA881X_BOOST_ATEST_CTL (WSA881X_ANALOG_BASE + 0x0039)
174*4882a593Smuzhiyun #define WSA881X_SPKR_PROT_FE_GAIN (WSA881X_ANALOG_BASE + 0x003A)
175*4882a593Smuzhiyun #define WSA881X_SPKR_PROT_FE_CM_LDO_SET (WSA881X_ANALOG_BASE + 0x003B)
176*4882a593Smuzhiyun #define WSA881X_SPKR_PROT_FE_ISENSE_BIAS_SET1 (WSA881X_ANALOG_BASE + 0x003C)
177*4882a593Smuzhiyun #define WSA881X_SPKR_PROT_FE_ISENSE_BIAS_SET2 (WSA881X_ANALOG_BASE + 0x003D)
178*4882a593Smuzhiyun #define WSA881X_SPKR_PROT_ATEST1 (WSA881X_ANALOG_BASE + 0x003E)
179*4882a593Smuzhiyun #define WSA881X_SPKR_PROT_ATEST2 (WSA881X_ANALOG_BASE + 0x003F)
180*4882a593Smuzhiyun #define WSA881X_SPKR_PROT_FE_VSENSE_VCM (WSA881X_ANALOG_BASE + 0x0040)
181*4882a593Smuzhiyun #define WSA881X_SPKR_PROT_FE_VSENSE_BIAS_SET1 (WSA881X_ANALOG_BASE + 0x0041)
182*4882a593Smuzhiyun #define WSA881X_BONGO_RESRV_REG1 (WSA881X_ANALOG_BASE + 0x0042)
183*4882a593Smuzhiyun #define WSA881X_BONGO_RESRV_REG2 (WSA881X_ANALOG_BASE + 0x0043)
184*4882a593Smuzhiyun #define WSA881X_SPKR_PROT_SAR (WSA881X_ANALOG_BASE + 0x0044)
185*4882a593Smuzhiyun #define WSA881X_SPKR_STATUS3 (WSA881X_ANALOG_BASE + 0x0045)
186*4882a593Smuzhiyun
187*4882a593Smuzhiyun #define SWRS_SCP_FRAME_CTRL_BANK(m) (0x60 + 0x10 * (m))
188*4882a593Smuzhiyun #define SWRS_SCP_HOST_CLK_DIV2_CTL_BANK(m) (0xE0 + 0x10 * (m))
189*4882a593Smuzhiyun #define SWR_SLV_MAX_REG_ADDR 0x390
190*4882a593Smuzhiyun #define SWR_SLV_START_REG_ADDR 0x40
191*4882a593Smuzhiyun #define SWR_SLV_MAX_BUF_LEN 20
192*4882a593Smuzhiyun #define BYTES_PER_LINE 12
193*4882a593Smuzhiyun #define SWR_SLV_RD_BUF_LEN 8
194*4882a593Smuzhiyun #define SWR_SLV_WR_BUF_LEN 32
195*4882a593Smuzhiyun #define SWR_SLV_MAX_DEVICES 2
196*4882a593Smuzhiyun #define WSA881X_MAX_SWR_PORTS 4
197*4882a593Smuzhiyun #define WSA881X_VERSION_ENTRY_SIZE 27
198*4882a593Smuzhiyun #define WSA881X_OCP_CTL_TIMER_SEC 2
199*4882a593Smuzhiyun #define WSA881X_OCP_CTL_TEMP_CELSIUS 25
200*4882a593Smuzhiyun #define WSA881X_OCP_CTL_POLL_TIMER_SEC 60
201*4882a593Smuzhiyun
202*4882a593Smuzhiyun #define WSA881X_PA_GAIN_TLV(xname, reg, shift, max, invert, tlv_array) \
203*4882a593Smuzhiyun { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
204*4882a593Smuzhiyun .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\
205*4882a593Smuzhiyun SNDRV_CTL_ELEM_ACCESS_READWRITE,\
206*4882a593Smuzhiyun .tlv.p = (tlv_array), \
207*4882a593Smuzhiyun .info = snd_soc_info_volsw, .get = snd_soc_get_volsw,\
208*4882a593Smuzhiyun .put = wsa881x_put_pa_gain, \
209*4882a593Smuzhiyun .private_value = SOC_SINGLE_VALUE(reg, shift, max, invert, 0) }
210*4882a593Smuzhiyun
211*4882a593Smuzhiyun static struct reg_default wsa881x_defaults[] = {
212*4882a593Smuzhiyun { WSA881X_CHIP_ID0, 0x00 },
213*4882a593Smuzhiyun { WSA881X_CHIP_ID1, 0x00 },
214*4882a593Smuzhiyun { WSA881X_CHIP_ID2, 0x00 },
215*4882a593Smuzhiyun { WSA881X_CHIP_ID3, 0x02 },
216*4882a593Smuzhiyun { WSA881X_BUS_ID, 0x00 },
217*4882a593Smuzhiyun { WSA881X_CDC_RST_CTL, 0x00 },
218*4882a593Smuzhiyun { WSA881X_CDC_TOP_CLK_CTL, 0x03 },
219*4882a593Smuzhiyun { WSA881X_CDC_ANA_CLK_CTL, 0x00 },
220*4882a593Smuzhiyun { WSA881X_CDC_DIG_CLK_CTL, 0x00 },
221*4882a593Smuzhiyun { WSA881X_CLOCK_CONFIG, 0x00 },
222*4882a593Smuzhiyun { WSA881X_ANA_CTL, 0x08 },
223*4882a593Smuzhiyun { WSA881X_SWR_RESET_EN, 0x00 },
224*4882a593Smuzhiyun { WSA881X_TEMP_DETECT_CTL, 0x01 },
225*4882a593Smuzhiyun { WSA881X_TEMP_MSB, 0x00 },
226*4882a593Smuzhiyun { WSA881X_TEMP_LSB, 0x00 },
227*4882a593Smuzhiyun { WSA881X_TEMP_CONFIG0, 0x00 },
228*4882a593Smuzhiyun { WSA881X_TEMP_CONFIG1, 0x00 },
229*4882a593Smuzhiyun { WSA881X_CDC_CLIP_CTL, 0x03 },
230*4882a593Smuzhiyun { WSA881X_SDM_PDM9_LSB, 0x00 },
231*4882a593Smuzhiyun { WSA881X_SDM_PDM9_MSB, 0x00 },
232*4882a593Smuzhiyun { WSA881X_CDC_RX_CTL, 0x7E },
233*4882a593Smuzhiyun { WSA881X_DEM_BYPASS_DATA0, 0x00 },
234*4882a593Smuzhiyun { WSA881X_DEM_BYPASS_DATA1, 0x00 },
235*4882a593Smuzhiyun { WSA881X_DEM_BYPASS_DATA2, 0x00 },
236*4882a593Smuzhiyun { WSA881X_DEM_BYPASS_DATA3, 0x00 },
237*4882a593Smuzhiyun { WSA881X_OTP_CTRL0, 0x00 },
238*4882a593Smuzhiyun { WSA881X_OTP_CTRL1, 0x00 },
239*4882a593Smuzhiyun { WSA881X_HDRIVE_CTL_GROUP1, 0x00 },
240*4882a593Smuzhiyun { WSA881X_INTR_MODE, 0x00 },
241*4882a593Smuzhiyun { WSA881X_INTR_STATUS, 0x00 },
242*4882a593Smuzhiyun { WSA881X_INTR_CLEAR, 0x00 },
243*4882a593Smuzhiyun { WSA881X_INTR_LEVEL, 0x00 },
244*4882a593Smuzhiyun { WSA881X_INTR_SET, 0x00 },
245*4882a593Smuzhiyun { WSA881X_INTR_TEST, 0x00 },
246*4882a593Smuzhiyun { WSA881X_PDM_TEST_MODE, 0x00 },
247*4882a593Smuzhiyun { WSA881X_ATE_TEST_MODE, 0x00 },
248*4882a593Smuzhiyun { WSA881X_PIN_CTL_MODE, 0x00 },
249*4882a593Smuzhiyun { WSA881X_PIN_CTL_OE, 0x00 },
250*4882a593Smuzhiyun { WSA881X_PIN_WDATA_IOPAD, 0x00 },
251*4882a593Smuzhiyun { WSA881X_PIN_STATUS, 0x00 },
252*4882a593Smuzhiyun { WSA881X_DIG_DEBUG_MODE, 0x00 },
253*4882a593Smuzhiyun { WSA881X_DIG_DEBUG_SEL, 0x00 },
254*4882a593Smuzhiyun { WSA881X_DIG_DEBUG_EN, 0x00 },
255*4882a593Smuzhiyun { WSA881X_SWR_HM_TEST1, 0x08 },
256*4882a593Smuzhiyun { WSA881X_SWR_HM_TEST2, 0x00 },
257*4882a593Smuzhiyun { WSA881X_TEMP_DETECT_DBG_CTL, 0x00 },
258*4882a593Smuzhiyun { WSA881X_TEMP_DEBUG_MSB, 0x00 },
259*4882a593Smuzhiyun { WSA881X_TEMP_DEBUG_LSB, 0x00 },
260*4882a593Smuzhiyun { WSA881X_SAMPLE_EDGE_SEL, 0x0C },
261*4882a593Smuzhiyun { WSA881X_SPARE_0, 0x00 },
262*4882a593Smuzhiyun { WSA881X_SPARE_1, 0x00 },
263*4882a593Smuzhiyun { WSA881X_SPARE_2, 0x00 },
264*4882a593Smuzhiyun { WSA881X_OTP_REG_0, 0x01 },
265*4882a593Smuzhiyun { WSA881X_OTP_REG_1, 0xFF },
266*4882a593Smuzhiyun { WSA881X_OTP_REG_2, 0xC0 },
267*4882a593Smuzhiyun { WSA881X_OTP_REG_3, 0xFF },
268*4882a593Smuzhiyun { WSA881X_OTP_REG_4, 0xC0 },
269*4882a593Smuzhiyun { WSA881X_OTP_REG_5, 0xFF },
270*4882a593Smuzhiyun { WSA881X_OTP_REG_6, 0xFF },
271*4882a593Smuzhiyun { WSA881X_OTP_REG_7, 0xFF },
272*4882a593Smuzhiyun { WSA881X_OTP_REG_8, 0xFF },
273*4882a593Smuzhiyun { WSA881X_OTP_REG_9, 0xFF },
274*4882a593Smuzhiyun { WSA881X_OTP_REG_10, 0xFF },
275*4882a593Smuzhiyun { WSA881X_OTP_REG_11, 0xFF },
276*4882a593Smuzhiyun { WSA881X_OTP_REG_12, 0xFF },
277*4882a593Smuzhiyun { WSA881X_OTP_REG_13, 0xFF },
278*4882a593Smuzhiyun { WSA881X_OTP_REG_14, 0xFF },
279*4882a593Smuzhiyun { WSA881X_OTP_REG_15, 0xFF },
280*4882a593Smuzhiyun { WSA881X_OTP_REG_16, 0xFF },
281*4882a593Smuzhiyun { WSA881X_OTP_REG_17, 0xFF },
282*4882a593Smuzhiyun { WSA881X_OTP_REG_18, 0xFF },
283*4882a593Smuzhiyun { WSA881X_OTP_REG_19, 0xFF },
284*4882a593Smuzhiyun { WSA881X_OTP_REG_20, 0xFF },
285*4882a593Smuzhiyun { WSA881X_OTP_REG_21, 0xFF },
286*4882a593Smuzhiyun { WSA881X_OTP_REG_22, 0xFF },
287*4882a593Smuzhiyun { WSA881X_OTP_REG_23, 0xFF },
288*4882a593Smuzhiyun { WSA881X_OTP_REG_24, 0x03 },
289*4882a593Smuzhiyun { WSA881X_OTP_REG_25, 0x01 },
290*4882a593Smuzhiyun { WSA881X_OTP_REG_26, 0x03 },
291*4882a593Smuzhiyun { WSA881X_OTP_REG_27, 0x11 },
292*4882a593Smuzhiyun { WSA881X_OTP_REG_63, 0x40 },
293*4882a593Smuzhiyun /* WSA881x Analog registers */
294*4882a593Smuzhiyun { WSA881X_BIAS_REF_CTRL, 0x6C },
295*4882a593Smuzhiyun { WSA881X_BIAS_TEST, 0x16 },
296*4882a593Smuzhiyun { WSA881X_BIAS_BIAS, 0xF0 },
297*4882a593Smuzhiyun { WSA881X_TEMP_OP, 0x00 },
298*4882a593Smuzhiyun { WSA881X_TEMP_IREF_CTRL, 0x56 },
299*4882a593Smuzhiyun { WSA881X_TEMP_ISENS_CTRL, 0x47 },
300*4882a593Smuzhiyun { WSA881X_TEMP_CLK_CTRL, 0x87 },
301*4882a593Smuzhiyun { WSA881X_TEMP_TEST, 0x00 },
302*4882a593Smuzhiyun { WSA881X_TEMP_BIAS, 0x51 },
303*4882a593Smuzhiyun { WSA881X_TEMP_DOUT_MSB, 0x00 },
304*4882a593Smuzhiyun { WSA881X_TEMP_DOUT_LSB, 0x00 },
305*4882a593Smuzhiyun { WSA881X_ADC_EN_MODU_V, 0x00 },
306*4882a593Smuzhiyun { WSA881X_ADC_EN_MODU_I, 0x00 },
307*4882a593Smuzhiyun { WSA881X_ADC_EN_DET_TEST_V, 0x00 },
308*4882a593Smuzhiyun { WSA881X_ADC_EN_DET_TEST_I, 0x00 },
309*4882a593Smuzhiyun { WSA881X_ADC_EN_SEL_IBAIS, 0x10 },
310*4882a593Smuzhiyun { WSA881X_SPKR_DRV_EN, 0x74 },
311*4882a593Smuzhiyun { WSA881X_SPKR_DRV_DBG, 0x15 },
312*4882a593Smuzhiyun { WSA881X_SPKR_PWRSTG_DBG, 0x00 },
313*4882a593Smuzhiyun { WSA881X_SPKR_OCP_CTL, 0xD4 },
314*4882a593Smuzhiyun { WSA881X_SPKR_CLIP_CTL, 0x90 },
315*4882a593Smuzhiyun { WSA881X_SPKR_PA_INT, 0x54 },
316*4882a593Smuzhiyun { WSA881X_SPKR_BIAS_CAL, 0xAC },
317*4882a593Smuzhiyun { WSA881X_SPKR_STATUS1, 0x00 },
318*4882a593Smuzhiyun { WSA881X_SPKR_STATUS2, 0x00 },
319*4882a593Smuzhiyun { WSA881X_BOOST_EN_CTL, 0x18 },
320*4882a593Smuzhiyun { WSA881X_BOOST_CURRENT_LIMIT, 0x7A },
321*4882a593Smuzhiyun { WSA881X_BOOST_PRESET_OUT2, 0x70 },
322*4882a593Smuzhiyun { WSA881X_BOOST_FORCE_OUT, 0x0E },
323*4882a593Smuzhiyun { WSA881X_BOOST_LDO_PROG, 0x16 },
324*4882a593Smuzhiyun { WSA881X_BOOST_SLOPE_COMP_ISENSE_FB, 0x71 },
325*4882a593Smuzhiyun { WSA881X_BOOST_RON_CTL, 0x0F },
326*4882a593Smuzhiyun { WSA881X_BOOST_ZX_CTL, 0x34 },
327*4882a593Smuzhiyun { WSA881X_BOOST_START_CTL, 0x23 },
328*4882a593Smuzhiyun { WSA881X_BOOST_MISC1_CTL, 0x80 },
329*4882a593Smuzhiyun { WSA881X_BOOST_MISC2_CTL, 0x00 },
330*4882a593Smuzhiyun { WSA881X_BOOST_MISC3_CTL, 0x00 },
331*4882a593Smuzhiyun { WSA881X_BOOST_ATEST_CTL, 0x00 },
332*4882a593Smuzhiyun { WSA881X_SPKR_PROT_FE_GAIN, 0x46 },
333*4882a593Smuzhiyun { WSA881X_SPKR_PROT_FE_CM_LDO_SET, 0x3B },
334*4882a593Smuzhiyun { WSA881X_SPKR_PROT_FE_ISENSE_BIAS_SET1, 0x8D },
335*4882a593Smuzhiyun { WSA881X_SPKR_PROT_FE_ISENSE_BIAS_SET2, 0x8D },
336*4882a593Smuzhiyun { WSA881X_SPKR_PROT_ATEST1, 0x01 },
337*4882a593Smuzhiyun { WSA881X_SPKR_PROT_FE_VSENSE_VCM, 0x8D },
338*4882a593Smuzhiyun { WSA881X_SPKR_PROT_FE_VSENSE_BIAS_SET1, 0x4D },
339*4882a593Smuzhiyun { WSA881X_SPKR_PROT_SAR, 0x00 },
340*4882a593Smuzhiyun { WSA881X_SPKR_STATUS3, 0x00 },
341*4882a593Smuzhiyun };
342*4882a593Smuzhiyun
343*4882a593Smuzhiyun static const struct reg_sequence wsa881x_pre_pmu_pa_2_0[] = {
344*4882a593Smuzhiyun { WSA881X_SPKR_DRV_GAIN, 0x41, 0 },
345*4882a593Smuzhiyun { WSA881X_SPKR_MISC_CTL1, 0x87, 0 },
346*4882a593Smuzhiyun };
347*4882a593Smuzhiyun
348*4882a593Smuzhiyun static const struct reg_sequence wsa881x_vi_txfe_en_2_0[] = {
349*4882a593Smuzhiyun { WSA881X_SPKR_PROT_FE_VSENSE_VCM, 0x85, 0 },
350*4882a593Smuzhiyun { WSA881X_SPKR_PROT_ATEST2, 0x0A, 0 },
351*4882a593Smuzhiyun { WSA881X_SPKR_PROT_FE_GAIN, 0x47, 0 },
352*4882a593Smuzhiyun };
353*4882a593Smuzhiyun
354*4882a593Smuzhiyun /* Default register reset values for WSA881x rev 2.0 */
355*4882a593Smuzhiyun static struct reg_sequence wsa881x_rev_2_0[] = {
356*4882a593Smuzhiyun { WSA881X_RESET_CTL, 0x00, 0x00 },
357*4882a593Smuzhiyun { WSA881X_TADC_VALUE_CTL, 0x01, 0x00 },
358*4882a593Smuzhiyun { WSA881X_INTR_MASK, 0x1B, 0x00 },
359*4882a593Smuzhiyun { WSA881X_IOPAD_CTL, 0x00, 0x00 },
360*4882a593Smuzhiyun { WSA881X_OTP_REG_28, 0x3F, 0x00 },
361*4882a593Smuzhiyun { WSA881X_OTP_REG_29, 0x3F, 0x00 },
362*4882a593Smuzhiyun { WSA881X_OTP_REG_30, 0x01, 0x00 },
363*4882a593Smuzhiyun { WSA881X_OTP_REG_31, 0x01, 0x00 },
364*4882a593Smuzhiyun { WSA881X_TEMP_ADC_CTRL, 0x03, 0x00 },
365*4882a593Smuzhiyun { WSA881X_ADC_SEL_IBIAS, 0x45, 0x00 },
366*4882a593Smuzhiyun { WSA881X_SPKR_DRV_GAIN, 0xC1, 0x00 },
367*4882a593Smuzhiyun { WSA881X_SPKR_DAC_CTL, 0x42, 0x00 },
368*4882a593Smuzhiyun { WSA881X_SPKR_BBM_CTL, 0x02, 0x00 },
369*4882a593Smuzhiyun { WSA881X_SPKR_MISC_CTL1, 0x40, 0x00 },
370*4882a593Smuzhiyun { WSA881X_SPKR_MISC_CTL2, 0x07, 0x00 },
371*4882a593Smuzhiyun { WSA881X_SPKR_BIAS_INT, 0x5F, 0x00 },
372*4882a593Smuzhiyun { WSA881X_SPKR_BIAS_PSRR, 0x44, 0x00 },
373*4882a593Smuzhiyun { WSA881X_BOOST_PS_CTL, 0xA0, 0x00 },
374*4882a593Smuzhiyun { WSA881X_BOOST_PRESET_OUT1, 0xB7, 0x00 },
375*4882a593Smuzhiyun { WSA881X_BOOST_LOOP_STABILITY, 0x8D, 0x00 },
376*4882a593Smuzhiyun { WSA881X_SPKR_PROT_ATEST2, 0x02, 0x00 },
377*4882a593Smuzhiyun { WSA881X_BONGO_RESRV_REG1, 0x5E, 0x00 },
378*4882a593Smuzhiyun { WSA881X_BONGO_RESRV_REG2, 0x07, 0x00 },
379*4882a593Smuzhiyun };
380*4882a593Smuzhiyun
381*4882a593Smuzhiyun enum wsa_port_ids {
382*4882a593Smuzhiyun WSA881X_PORT_DAC,
383*4882a593Smuzhiyun WSA881X_PORT_COMP,
384*4882a593Smuzhiyun WSA881X_PORT_BOOST,
385*4882a593Smuzhiyun WSA881X_PORT_VISENSE,
386*4882a593Smuzhiyun };
387*4882a593Smuzhiyun
388*4882a593Smuzhiyun /* 4 ports */
389*4882a593Smuzhiyun static struct sdw_dpn_prop wsa_sink_dpn_prop[WSA881X_MAX_SWR_PORTS] = {
390*4882a593Smuzhiyun {
391*4882a593Smuzhiyun /* DAC */
392*4882a593Smuzhiyun .num = 1,
393*4882a593Smuzhiyun .type = SDW_DPN_SIMPLE,
394*4882a593Smuzhiyun .min_ch = 1,
395*4882a593Smuzhiyun .max_ch = 1,
396*4882a593Smuzhiyun .simple_ch_prep_sm = true,
397*4882a593Smuzhiyun .read_only_wordlength = true,
398*4882a593Smuzhiyun }, {
399*4882a593Smuzhiyun /* COMP */
400*4882a593Smuzhiyun .num = 2,
401*4882a593Smuzhiyun .type = SDW_DPN_SIMPLE,
402*4882a593Smuzhiyun .min_ch = 1,
403*4882a593Smuzhiyun .max_ch = 1,
404*4882a593Smuzhiyun .simple_ch_prep_sm = true,
405*4882a593Smuzhiyun .read_only_wordlength = true,
406*4882a593Smuzhiyun }, {
407*4882a593Smuzhiyun /* BOOST */
408*4882a593Smuzhiyun .num = 3,
409*4882a593Smuzhiyun .type = SDW_DPN_SIMPLE,
410*4882a593Smuzhiyun .min_ch = 1,
411*4882a593Smuzhiyun .max_ch = 1,
412*4882a593Smuzhiyun .simple_ch_prep_sm = true,
413*4882a593Smuzhiyun .read_only_wordlength = true,
414*4882a593Smuzhiyun }, {
415*4882a593Smuzhiyun /* VISENSE */
416*4882a593Smuzhiyun .num = 4,
417*4882a593Smuzhiyun .type = SDW_DPN_SIMPLE,
418*4882a593Smuzhiyun .min_ch = 1,
419*4882a593Smuzhiyun .max_ch = 1,
420*4882a593Smuzhiyun .simple_ch_prep_sm = true,
421*4882a593Smuzhiyun .read_only_wordlength = true,
422*4882a593Smuzhiyun }
423*4882a593Smuzhiyun };
424*4882a593Smuzhiyun
425*4882a593Smuzhiyun static struct sdw_port_config wsa881x_pconfig[WSA881X_MAX_SWR_PORTS] = {
426*4882a593Smuzhiyun {
427*4882a593Smuzhiyun .num = 1,
428*4882a593Smuzhiyun .ch_mask = 0x1,
429*4882a593Smuzhiyun }, {
430*4882a593Smuzhiyun .num = 2,
431*4882a593Smuzhiyun .ch_mask = 0xf,
432*4882a593Smuzhiyun }, {
433*4882a593Smuzhiyun .num = 3,
434*4882a593Smuzhiyun .ch_mask = 0x3,
435*4882a593Smuzhiyun }, { /* IV feedback */
436*4882a593Smuzhiyun .num = 4,
437*4882a593Smuzhiyun .ch_mask = 0x3,
438*4882a593Smuzhiyun },
439*4882a593Smuzhiyun };
440*4882a593Smuzhiyun
wsa881x_readable_register(struct device * dev,unsigned int reg)441*4882a593Smuzhiyun static bool wsa881x_readable_register(struct device *dev, unsigned int reg)
442*4882a593Smuzhiyun {
443*4882a593Smuzhiyun switch (reg) {
444*4882a593Smuzhiyun case WSA881X_CHIP_ID0:
445*4882a593Smuzhiyun case WSA881X_CHIP_ID1:
446*4882a593Smuzhiyun case WSA881X_CHIP_ID2:
447*4882a593Smuzhiyun case WSA881X_CHIP_ID3:
448*4882a593Smuzhiyun case WSA881X_BUS_ID:
449*4882a593Smuzhiyun case WSA881X_CDC_RST_CTL:
450*4882a593Smuzhiyun case WSA881X_CDC_TOP_CLK_CTL:
451*4882a593Smuzhiyun case WSA881X_CDC_ANA_CLK_CTL:
452*4882a593Smuzhiyun case WSA881X_CDC_DIG_CLK_CTL:
453*4882a593Smuzhiyun case WSA881X_CLOCK_CONFIG:
454*4882a593Smuzhiyun case WSA881X_ANA_CTL:
455*4882a593Smuzhiyun case WSA881X_SWR_RESET_EN:
456*4882a593Smuzhiyun case WSA881X_RESET_CTL:
457*4882a593Smuzhiyun case WSA881X_TADC_VALUE_CTL:
458*4882a593Smuzhiyun case WSA881X_TEMP_DETECT_CTL:
459*4882a593Smuzhiyun case WSA881X_TEMP_MSB:
460*4882a593Smuzhiyun case WSA881X_TEMP_LSB:
461*4882a593Smuzhiyun case WSA881X_TEMP_CONFIG0:
462*4882a593Smuzhiyun case WSA881X_TEMP_CONFIG1:
463*4882a593Smuzhiyun case WSA881X_CDC_CLIP_CTL:
464*4882a593Smuzhiyun case WSA881X_SDM_PDM9_LSB:
465*4882a593Smuzhiyun case WSA881X_SDM_PDM9_MSB:
466*4882a593Smuzhiyun case WSA881X_CDC_RX_CTL:
467*4882a593Smuzhiyun case WSA881X_DEM_BYPASS_DATA0:
468*4882a593Smuzhiyun case WSA881X_DEM_BYPASS_DATA1:
469*4882a593Smuzhiyun case WSA881X_DEM_BYPASS_DATA2:
470*4882a593Smuzhiyun case WSA881X_DEM_BYPASS_DATA3:
471*4882a593Smuzhiyun case WSA881X_OTP_CTRL0:
472*4882a593Smuzhiyun case WSA881X_OTP_CTRL1:
473*4882a593Smuzhiyun case WSA881X_HDRIVE_CTL_GROUP1:
474*4882a593Smuzhiyun case WSA881X_INTR_MODE:
475*4882a593Smuzhiyun case WSA881X_INTR_MASK:
476*4882a593Smuzhiyun case WSA881X_INTR_STATUS:
477*4882a593Smuzhiyun case WSA881X_INTR_CLEAR:
478*4882a593Smuzhiyun case WSA881X_INTR_LEVEL:
479*4882a593Smuzhiyun case WSA881X_INTR_SET:
480*4882a593Smuzhiyun case WSA881X_INTR_TEST:
481*4882a593Smuzhiyun case WSA881X_PDM_TEST_MODE:
482*4882a593Smuzhiyun case WSA881X_ATE_TEST_MODE:
483*4882a593Smuzhiyun case WSA881X_PIN_CTL_MODE:
484*4882a593Smuzhiyun case WSA881X_PIN_CTL_OE:
485*4882a593Smuzhiyun case WSA881X_PIN_WDATA_IOPAD:
486*4882a593Smuzhiyun case WSA881X_PIN_STATUS:
487*4882a593Smuzhiyun case WSA881X_DIG_DEBUG_MODE:
488*4882a593Smuzhiyun case WSA881X_DIG_DEBUG_SEL:
489*4882a593Smuzhiyun case WSA881X_DIG_DEBUG_EN:
490*4882a593Smuzhiyun case WSA881X_SWR_HM_TEST1:
491*4882a593Smuzhiyun case WSA881X_SWR_HM_TEST2:
492*4882a593Smuzhiyun case WSA881X_TEMP_DETECT_DBG_CTL:
493*4882a593Smuzhiyun case WSA881X_TEMP_DEBUG_MSB:
494*4882a593Smuzhiyun case WSA881X_TEMP_DEBUG_LSB:
495*4882a593Smuzhiyun case WSA881X_SAMPLE_EDGE_SEL:
496*4882a593Smuzhiyun case WSA881X_IOPAD_CTL:
497*4882a593Smuzhiyun case WSA881X_SPARE_0:
498*4882a593Smuzhiyun case WSA881X_SPARE_1:
499*4882a593Smuzhiyun case WSA881X_SPARE_2:
500*4882a593Smuzhiyun case WSA881X_OTP_REG_0:
501*4882a593Smuzhiyun case WSA881X_OTP_REG_1:
502*4882a593Smuzhiyun case WSA881X_OTP_REG_2:
503*4882a593Smuzhiyun case WSA881X_OTP_REG_3:
504*4882a593Smuzhiyun case WSA881X_OTP_REG_4:
505*4882a593Smuzhiyun case WSA881X_OTP_REG_5:
506*4882a593Smuzhiyun case WSA881X_OTP_REG_6:
507*4882a593Smuzhiyun case WSA881X_OTP_REG_7:
508*4882a593Smuzhiyun case WSA881X_OTP_REG_8:
509*4882a593Smuzhiyun case WSA881X_OTP_REG_9:
510*4882a593Smuzhiyun case WSA881X_OTP_REG_10:
511*4882a593Smuzhiyun case WSA881X_OTP_REG_11:
512*4882a593Smuzhiyun case WSA881X_OTP_REG_12:
513*4882a593Smuzhiyun case WSA881X_OTP_REG_13:
514*4882a593Smuzhiyun case WSA881X_OTP_REG_14:
515*4882a593Smuzhiyun case WSA881X_OTP_REG_15:
516*4882a593Smuzhiyun case WSA881X_OTP_REG_16:
517*4882a593Smuzhiyun case WSA881X_OTP_REG_17:
518*4882a593Smuzhiyun case WSA881X_OTP_REG_18:
519*4882a593Smuzhiyun case WSA881X_OTP_REG_19:
520*4882a593Smuzhiyun case WSA881X_OTP_REG_20:
521*4882a593Smuzhiyun case WSA881X_OTP_REG_21:
522*4882a593Smuzhiyun case WSA881X_OTP_REG_22:
523*4882a593Smuzhiyun case WSA881X_OTP_REG_23:
524*4882a593Smuzhiyun case WSA881X_OTP_REG_24:
525*4882a593Smuzhiyun case WSA881X_OTP_REG_25:
526*4882a593Smuzhiyun case WSA881X_OTP_REG_26:
527*4882a593Smuzhiyun case WSA881X_OTP_REG_27:
528*4882a593Smuzhiyun case WSA881X_OTP_REG_28:
529*4882a593Smuzhiyun case WSA881X_OTP_REG_29:
530*4882a593Smuzhiyun case WSA881X_OTP_REG_30:
531*4882a593Smuzhiyun case WSA881X_OTP_REG_31:
532*4882a593Smuzhiyun case WSA881X_OTP_REG_63:
533*4882a593Smuzhiyun case WSA881X_BIAS_REF_CTRL:
534*4882a593Smuzhiyun case WSA881X_BIAS_TEST:
535*4882a593Smuzhiyun case WSA881X_BIAS_BIAS:
536*4882a593Smuzhiyun case WSA881X_TEMP_OP:
537*4882a593Smuzhiyun case WSA881X_TEMP_IREF_CTRL:
538*4882a593Smuzhiyun case WSA881X_TEMP_ISENS_CTRL:
539*4882a593Smuzhiyun case WSA881X_TEMP_CLK_CTRL:
540*4882a593Smuzhiyun case WSA881X_TEMP_TEST:
541*4882a593Smuzhiyun case WSA881X_TEMP_BIAS:
542*4882a593Smuzhiyun case WSA881X_TEMP_ADC_CTRL:
543*4882a593Smuzhiyun case WSA881X_TEMP_DOUT_MSB:
544*4882a593Smuzhiyun case WSA881X_TEMP_DOUT_LSB:
545*4882a593Smuzhiyun case WSA881X_ADC_EN_MODU_V:
546*4882a593Smuzhiyun case WSA881X_ADC_EN_MODU_I:
547*4882a593Smuzhiyun case WSA881X_ADC_EN_DET_TEST_V:
548*4882a593Smuzhiyun case WSA881X_ADC_EN_DET_TEST_I:
549*4882a593Smuzhiyun case WSA881X_ADC_SEL_IBIAS:
550*4882a593Smuzhiyun case WSA881X_ADC_EN_SEL_IBAIS:
551*4882a593Smuzhiyun case WSA881X_SPKR_DRV_EN:
552*4882a593Smuzhiyun case WSA881X_SPKR_DRV_GAIN:
553*4882a593Smuzhiyun case WSA881X_SPKR_DAC_CTL:
554*4882a593Smuzhiyun case WSA881X_SPKR_DRV_DBG:
555*4882a593Smuzhiyun case WSA881X_SPKR_PWRSTG_DBG:
556*4882a593Smuzhiyun case WSA881X_SPKR_OCP_CTL:
557*4882a593Smuzhiyun case WSA881X_SPKR_CLIP_CTL:
558*4882a593Smuzhiyun case WSA881X_SPKR_BBM_CTL:
559*4882a593Smuzhiyun case WSA881X_SPKR_MISC_CTL1:
560*4882a593Smuzhiyun case WSA881X_SPKR_MISC_CTL2:
561*4882a593Smuzhiyun case WSA881X_SPKR_BIAS_INT:
562*4882a593Smuzhiyun case WSA881X_SPKR_PA_INT:
563*4882a593Smuzhiyun case WSA881X_SPKR_BIAS_CAL:
564*4882a593Smuzhiyun case WSA881X_SPKR_BIAS_PSRR:
565*4882a593Smuzhiyun case WSA881X_SPKR_STATUS1:
566*4882a593Smuzhiyun case WSA881X_SPKR_STATUS2:
567*4882a593Smuzhiyun case WSA881X_BOOST_EN_CTL:
568*4882a593Smuzhiyun case WSA881X_BOOST_CURRENT_LIMIT:
569*4882a593Smuzhiyun case WSA881X_BOOST_PS_CTL:
570*4882a593Smuzhiyun case WSA881X_BOOST_PRESET_OUT1:
571*4882a593Smuzhiyun case WSA881X_BOOST_PRESET_OUT2:
572*4882a593Smuzhiyun case WSA881X_BOOST_FORCE_OUT:
573*4882a593Smuzhiyun case WSA881X_BOOST_LDO_PROG:
574*4882a593Smuzhiyun case WSA881X_BOOST_SLOPE_COMP_ISENSE_FB:
575*4882a593Smuzhiyun case WSA881X_BOOST_RON_CTL:
576*4882a593Smuzhiyun case WSA881X_BOOST_LOOP_STABILITY:
577*4882a593Smuzhiyun case WSA881X_BOOST_ZX_CTL:
578*4882a593Smuzhiyun case WSA881X_BOOST_START_CTL:
579*4882a593Smuzhiyun case WSA881X_BOOST_MISC1_CTL:
580*4882a593Smuzhiyun case WSA881X_BOOST_MISC2_CTL:
581*4882a593Smuzhiyun case WSA881X_BOOST_MISC3_CTL:
582*4882a593Smuzhiyun case WSA881X_BOOST_ATEST_CTL:
583*4882a593Smuzhiyun case WSA881X_SPKR_PROT_FE_GAIN:
584*4882a593Smuzhiyun case WSA881X_SPKR_PROT_FE_CM_LDO_SET:
585*4882a593Smuzhiyun case WSA881X_SPKR_PROT_FE_ISENSE_BIAS_SET1:
586*4882a593Smuzhiyun case WSA881X_SPKR_PROT_FE_ISENSE_BIAS_SET2:
587*4882a593Smuzhiyun case WSA881X_SPKR_PROT_ATEST1:
588*4882a593Smuzhiyun case WSA881X_SPKR_PROT_ATEST2:
589*4882a593Smuzhiyun case WSA881X_SPKR_PROT_FE_VSENSE_VCM:
590*4882a593Smuzhiyun case WSA881X_SPKR_PROT_FE_VSENSE_BIAS_SET1:
591*4882a593Smuzhiyun case WSA881X_BONGO_RESRV_REG1:
592*4882a593Smuzhiyun case WSA881X_BONGO_RESRV_REG2:
593*4882a593Smuzhiyun case WSA881X_SPKR_PROT_SAR:
594*4882a593Smuzhiyun case WSA881X_SPKR_STATUS3:
595*4882a593Smuzhiyun return true;
596*4882a593Smuzhiyun default:
597*4882a593Smuzhiyun return false;
598*4882a593Smuzhiyun }
599*4882a593Smuzhiyun }
600*4882a593Smuzhiyun
wsa881x_volatile_register(struct device * dev,unsigned int reg)601*4882a593Smuzhiyun static bool wsa881x_volatile_register(struct device *dev, unsigned int reg)
602*4882a593Smuzhiyun {
603*4882a593Smuzhiyun switch (reg) {
604*4882a593Smuzhiyun case WSA881X_CHIP_ID0:
605*4882a593Smuzhiyun case WSA881X_CHIP_ID1:
606*4882a593Smuzhiyun case WSA881X_CHIP_ID2:
607*4882a593Smuzhiyun case WSA881X_CHIP_ID3:
608*4882a593Smuzhiyun case WSA881X_BUS_ID:
609*4882a593Smuzhiyun case WSA881X_TEMP_MSB:
610*4882a593Smuzhiyun case WSA881X_TEMP_LSB:
611*4882a593Smuzhiyun case WSA881X_SDM_PDM9_LSB:
612*4882a593Smuzhiyun case WSA881X_SDM_PDM9_MSB:
613*4882a593Smuzhiyun case WSA881X_OTP_CTRL1:
614*4882a593Smuzhiyun case WSA881X_INTR_STATUS:
615*4882a593Smuzhiyun case WSA881X_ATE_TEST_MODE:
616*4882a593Smuzhiyun case WSA881X_PIN_STATUS:
617*4882a593Smuzhiyun case WSA881X_SWR_HM_TEST2:
618*4882a593Smuzhiyun case WSA881X_SPKR_STATUS1:
619*4882a593Smuzhiyun case WSA881X_SPKR_STATUS2:
620*4882a593Smuzhiyun case WSA881X_SPKR_STATUS3:
621*4882a593Smuzhiyun case WSA881X_OTP_REG_0:
622*4882a593Smuzhiyun case WSA881X_OTP_REG_1:
623*4882a593Smuzhiyun case WSA881X_OTP_REG_2:
624*4882a593Smuzhiyun case WSA881X_OTP_REG_3:
625*4882a593Smuzhiyun case WSA881X_OTP_REG_4:
626*4882a593Smuzhiyun case WSA881X_OTP_REG_5:
627*4882a593Smuzhiyun case WSA881X_OTP_REG_31:
628*4882a593Smuzhiyun case WSA881X_TEMP_DOUT_MSB:
629*4882a593Smuzhiyun case WSA881X_TEMP_DOUT_LSB:
630*4882a593Smuzhiyun case WSA881X_TEMP_OP:
631*4882a593Smuzhiyun case WSA881X_SPKR_PROT_SAR:
632*4882a593Smuzhiyun return true;
633*4882a593Smuzhiyun default:
634*4882a593Smuzhiyun return false;
635*4882a593Smuzhiyun }
636*4882a593Smuzhiyun }
637*4882a593Smuzhiyun
638*4882a593Smuzhiyun static struct regmap_config wsa881x_regmap_config = {
639*4882a593Smuzhiyun .reg_bits = 32,
640*4882a593Smuzhiyun .val_bits = 8,
641*4882a593Smuzhiyun .cache_type = REGCACHE_RBTREE,
642*4882a593Smuzhiyun .reg_defaults = wsa881x_defaults,
643*4882a593Smuzhiyun .max_register = WSA881X_SPKR_STATUS3,
644*4882a593Smuzhiyun .num_reg_defaults = ARRAY_SIZE(wsa881x_defaults),
645*4882a593Smuzhiyun .volatile_reg = wsa881x_volatile_register,
646*4882a593Smuzhiyun .readable_reg = wsa881x_readable_register,
647*4882a593Smuzhiyun .reg_format_endian = REGMAP_ENDIAN_NATIVE,
648*4882a593Smuzhiyun .val_format_endian = REGMAP_ENDIAN_NATIVE,
649*4882a593Smuzhiyun .can_multi_write = true,
650*4882a593Smuzhiyun };
651*4882a593Smuzhiyun
652*4882a593Smuzhiyun enum {
653*4882a593Smuzhiyun G_18DB = 0,
654*4882a593Smuzhiyun G_16P5DB,
655*4882a593Smuzhiyun G_15DB,
656*4882a593Smuzhiyun G_13P5DB,
657*4882a593Smuzhiyun G_12DB,
658*4882a593Smuzhiyun G_10P5DB,
659*4882a593Smuzhiyun G_9DB,
660*4882a593Smuzhiyun G_7P5DB,
661*4882a593Smuzhiyun G_6DB,
662*4882a593Smuzhiyun G_4P5DB,
663*4882a593Smuzhiyun G_3DB,
664*4882a593Smuzhiyun G_1P5DB,
665*4882a593Smuzhiyun G_0DB,
666*4882a593Smuzhiyun };
667*4882a593Smuzhiyun
668*4882a593Smuzhiyun /*
669*4882a593Smuzhiyun * Private data Structure for wsa881x. All parameters related to
670*4882a593Smuzhiyun * WSA881X codec needs to be defined here.
671*4882a593Smuzhiyun */
672*4882a593Smuzhiyun struct wsa881x_priv {
673*4882a593Smuzhiyun struct regmap *regmap;
674*4882a593Smuzhiyun struct device *dev;
675*4882a593Smuzhiyun struct sdw_slave *slave;
676*4882a593Smuzhiyun struct sdw_stream_config sconfig;
677*4882a593Smuzhiyun struct sdw_stream_runtime *sruntime;
678*4882a593Smuzhiyun struct sdw_port_config port_config[WSA881X_MAX_SWR_PORTS];
679*4882a593Smuzhiyun struct gpio_desc *sd_n;
680*4882a593Smuzhiyun int version;
681*4882a593Smuzhiyun int active_ports;
682*4882a593Smuzhiyun bool port_prepared[WSA881X_MAX_SWR_PORTS];
683*4882a593Smuzhiyun bool port_enable[WSA881X_MAX_SWR_PORTS];
684*4882a593Smuzhiyun };
685*4882a593Smuzhiyun
wsa881x_init(struct wsa881x_priv * wsa881x)686*4882a593Smuzhiyun static void wsa881x_init(struct wsa881x_priv *wsa881x)
687*4882a593Smuzhiyun {
688*4882a593Smuzhiyun struct regmap *rm = wsa881x->regmap;
689*4882a593Smuzhiyun unsigned int val = 0;
690*4882a593Smuzhiyun
691*4882a593Smuzhiyun regmap_read(rm, WSA881X_CHIP_ID1, &wsa881x->version);
692*4882a593Smuzhiyun regmap_register_patch(wsa881x->regmap, wsa881x_rev_2_0,
693*4882a593Smuzhiyun ARRAY_SIZE(wsa881x_rev_2_0));
694*4882a593Smuzhiyun
695*4882a593Smuzhiyun /* Enable software reset output from soundwire slave */
696*4882a593Smuzhiyun regmap_update_bits(rm, WSA881X_SWR_RESET_EN, 0x07, 0x07);
697*4882a593Smuzhiyun
698*4882a593Smuzhiyun /* Bring out of analog reset */
699*4882a593Smuzhiyun regmap_update_bits(rm, WSA881X_CDC_RST_CTL, 0x02, 0x02);
700*4882a593Smuzhiyun
701*4882a593Smuzhiyun /* Bring out of digital reset */
702*4882a593Smuzhiyun regmap_update_bits(rm, WSA881X_CDC_RST_CTL, 0x01, 0x01);
703*4882a593Smuzhiyun regmap_update_bits(rm, WSA881X_CLOCK_CONFIG, 0x10, 0x10);
704*4882a593Smuzhiyun regmap_update_bits(rm, WSA881X_SPKR_OCP_CTL, 0x02, 0x02);
705*4882a593Smuzhiyun regmap_update_bits(rm, WSA881X_SPKR_MISC_CTL1, 0xC0, 0x80);
706*4882a593Smuzhiyun regmap_update_bits(rm, WSA881X_SPKR_MISC_CTL1, 0x06, 0x06);
707*4882a593Smuzhiyun regmap_update_bits(rm, WSA881X_SPKR_BIAS_INT, 0xFF, 0x00);
708*4882a593Smuzhiyun regmap_update_bits(rm, WSA881X_SPKR_PA_INT, 0xF0, 0x40);
709*4882a593Smuzhiyun regmap_update_bits(rm, WSA881X_SPKR_PA_INT, 0x0E, 0x0E);
710*4882a593Smuzhiyun regmap_update_bits(rm, WSA881X_BOOST_LOOP_STABILITY, 0x03, 0x03);
711*4882a593Smuzhiyun regmap_update_bits(rm, WSA881X_BOOST_MISC2_CTL, 0xFF, 0x14);
712*4882a593Smuzhiyun regmap_update_bits(rm, WSA881X_BOOST_START_CTL, 0x80, 0x80);
713*4882a593Smuzhiyun regmap_update_bits(rm, WSA881X_BOOST_START_CTL, 0x03, 0x00);
714*4882a593Smuzhiyun regmap_update_bits(rm, WSA881X_BOOST_SLOPE_COMP_ISENSE_FB, 0x0C, 0x04);
715*4882a593Smuzhiyun regmap_update_bits(rm, WSA881X_BOOST_SLOPE_COMP_ISENSE_FB, 0x03, 0x00);
716*4882a593Smuzhiyun
717*4882a593Smuzhiyun regmap_read(rm, WSA881X_OTP_REG_0, &val);
718*4882a593Smuzhiyun if (val)
719*4882a593Smuzhiyun regmap_update_bits(rm, WSA881X_BOOST_PRESET_OUT1, 0xF0, 0x70);
720*4882a593Smuzhiyun
721*4882a593Smuzhiyun regmap_update_bits(rm, WSA881X_BOOST_PRESET_OUT2, 0xF0, 0x30);
722*4882a593Smuzhiyun regmap_update_bits(rm, WSA881X_SPKR_DRV_EN, 0x08, 0x08);
723*4882a593Smuzhiyun regmap_update_bits(rm, WSA881X_BOOST_CURRENT_LIMIT, 0x0F, 0x08);
724*4882a593Smuzhiyun regmap_update_bits(rm, WSA881X_SPKR_OCP_CTL, 0x30, 0x30);
725*4882a593Smuzhiyun regmap_update_bits(rm, WSA881X_SPKR_OCP_CTL, 0x0C, 0x00);
726*4882a593Smuzhiyun regmap_update_bits(rm, WSA881X_OTP_REG_28, 0x3F, 0x3A);
727*4882a593Smuzhiyun regmap_update_bits(rm, WSA881X_BONGO_RESRV_REG1, 0xFF, 0xB2);
728*4882a593Smuzhiyun regmap_update_bits(rm, WSA881X_BONGO_RESRV_REG2, 0xFF, 0x05);
729*4882a593Smuzhiyun }
730*4882a593Smuzhiyun
wsa881x_component_probe(struct snd_soc_component * comp)731*4882a593Smuzhiyun static int wsa881x_component_probe(struct snd_soc_component *comp)
732*4882a593Smuzhiyun {
733*4882a593Smuzhiyun struct wsa881x_priv *wsa881x = snd_soc_component_get_drvdata(comp);
734*4882a593Smuzhiyun
735*4882a593Smuzhiyun snd_soc_component_init_regmap(comp, wsa881x->regmap);
736*4882a593Smuzhiyun
737*4882a593Smuzhiyun return 0;
738*4882a593Smuzhiyun }
739*4882a593Smuzhiyun
wsa881x_put_pa_gain(struct snd_kcontrol * kc,struct snd_ctl_elem_value * ucontrol)740*4882a593Smuzhiyun static int wsa881x_put_pa_gain(struct snd_kcontrol *kc,
741*4882a593Smuzhiyun struct snd_ctl_elem_value *ucontrol)
742*4882a593Smuzhiyun {
743*4882a593Smuzhiyun struct snd_soc_component *comp = snd_soc_kcontrol_component(kc);
744*4882a593Smuzhiyun struct soc_mixer_control *mc =
745*4882a593Smuzhiyun (struct soc_mixer_control *)kc->private_value;
746*4882a593Smuzhiyun int max = mc->max;
747*4882a593Smuzhiyun unsigned int mask = (1 << fls(max)) - 1;
748*4882a593Smuzhiyun int val, ret, min_gain, max_gain;
749*4882a593Smuzhiyun
750*4882a593Smuzhiyun max_gain = (max - ucontrol->value.integer.value[0]) & mask;
751*4882a593Smuzhiyun /*
752*4882a593Smuzhiyun * Gain has to set incrementally in 4 steps
753*4882a593Smuzhiyun * as per HW sequence
754*4882a593Smuzhiyun */
755*4882a593Smuzhiyun if (max_gain > G_4P5DB)
756*4882a593Smuzhiyun min_gain = G_0DB;
757*4882a593Smuzhiyun else
758*4882a593Smuzhiyun min_gain = max_gain + 3;
759*4882a593Smuzhiyun /*
760*4882a593Smuzhiyun * 1ms delay is needed before change in gain
761*4882a593Smuzhiyun * as per HW requirement.
762*4882a593Smuzhiyun */
763*4882a593Smuzhiyun usleep_range(1000, 1010);
764*4882a593Smuzhiyun
765*4882a593Smuzhiyun for (val = min_gain; max_gain <= val; val--) {
766*4882a593Smuzhiyun ret = snd_soc_component_update_bits(comp,
767*4882a593Smuzhiyun WSA881X_SPKR_DRV_GAIN,
768*4882a593Smuzhiyun WSA881X_SPKR_PAG_GAIN_MASK,
769*4882a593Smuzhiyun val << 4);
770*4882a593Smuzhiyun if (ret < 0)
771*4882a593Smuzhiyun dev_err(comp->dev, "Failed to change PA gain");
772*4882a593Smuzhiyun
773*4882a593Smuzhiyun usleep_range(1000, 1010);
774*4882a593Smuzhiyun }
775*4882a593Smuzhiyun
776*4882a593Smuzhiyun return 1;
777*4882a593Smuzhiyun }
778*4882a593Smuzhiyun
wsa881x_get_port(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)779*4882a593Smuzhiyun static int wsa881x_get_port(struct snd_kcontrol *kcontrol,
780*4882a593Smuzhiyun struct snd_ctl_elem_value *ucontrol)
781*4882a593Smuzhiyun {
782*4882a593Smuzhiyun struct snd_soc_component *comp = snd_soc_kcontrol_component(kcontrol);
783*4882a593Smuzhiyun struct wsa881x_priv *data = snd_soc_component_get_drvdata(comp);
784*4882a593Smuzhiyun struct soc_mixer_control *mixer =
785*4882a593Smuzhiyun (struct soc_mixer_control *)kcontrol->private_value;
786*4882a593Smuzhiyun int portidx = mixer->reg;
787*4882a593Smuzhiyun
788*4882a593Smuzhiyun ucontrol->value.integer.value[0] = data->port_enable[portidx];
789*4882a593Smuzhiyun
790*4882a593Smuzhiyun
791*4882a593Smuzhiyun return 0;
792*4882a593Smuzhiyun }
793*4882a593Smuzhiyun
wsa881x_boost_ctrl(struct snd_soc_component * comp,bool enable)794*4882a593Smuzhiyun static int wsa881x_boost_ctrl(struct snd_soc_component *comp, bool enable)
795*4882a593Smuzhiyun {
796*4882a593Smuzhiyun if (enable)
797*4882a593Smuzhiyun snd_soc_component_update_bits(comp, WSA881X_BOOST_EN_CTL,
798*4882a593Smuzhiyun WSA881X_BOOST_EN_MASK,
799*4882a593Smuzhiyun WSA881X_BOOST_EN);
800*4882a593Smuzhiyun else
801*4882a593Smuzhiyun snd_soc_component_update_bits(comp, WSA881X_BOOST_EN_CTL,
802*4882a593Smuzhiyun WSA881X_BOOST_EN_MASK, 0);
803*4882a593Smuzhiyun /*
804*4882a593Smuzhiyun * 1.5ms sleep is needed after boost enable/disable as per
805*4882a593Smuzhiyun * HW requirement
806*4882a593Smuzhiyun */
807*4882a593Smuzhiyun usleep_range(1500, 1510);
808*4882a593Smuzhiyun return 0;
809*4882a593Smuzhiyun }
810*4882a593Smuzhiyun
wsa881x_set_port(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)811*4882a593Smuzhiyun static int wsa881x_set_port(struct snd_kcontrol *kcontrol,
812*4882a593Smuzhiyun struct snd_ctl_elem_value *ucontrol)
813*4882a593Smuzhiyun {
814*4882a593Smuzhiyun struct snd_soc_component *comp = snd_soc_kcontrol_component(kcontrol);
815*4882a593Smuzhiyun struct wsa881x_priv *data = snd_soc_component_get_drvdata(comp);
816*4882a593Smuzhiyun struct soc_mixer_control *mixer =
817*4882a593Smuzhiyun (struct soc_mixer_control *)kcontrol->private_value;
818*4882a593Smuzhiyun int portidx = mixer->reg;
819*4882a593Smuzhiyun
820*4882a593Smuzhiyun if (ucontrol->value.integer.value[0]) {
821*4882a593Smuzhiyun if (data->port_enable[portidx])
822*4882a593Smuzhiyun return 0;
823*4882a593Smuzhiyun
824*4882a593Smuzhiyun data->port_enable[portidx] = true;
825*4882a593Smuzhiyun } else {
826*4882a593Smuzhiyun if (!data->port_enable[portidx])
827*4882a593Smuzhiyun return 0;
828*4882a593Smuzhiyun
829*4882a593Smuzhiyun data->port_enable[portidx] = false;
830*4882a593Smuzhiyun }
831*4882a593Smuzhiyun
832*4882a593Smuzhiyun if (portidx == WSA881X_PORT_BOOST) /* Boost Switch */
833*4882a593Smuzhiyun wsa881x_boost_ctrl(comp, data->port_enable[portidx]);
834*4882a593Smuzhiyun
835*4882a593Smuzhiyun return 1;
836*4882a593Smuzhiyun }
837*4882a593Smuzhiyun
838*4882a593Smuzhiyun static const char * const smart_boost_lvl_text[] = {
839*4882a593Smuzhiyun "6.625 V", "6.750 V", "6.875 V", "7.000 V",
840*4882a593Smuzhiyun "7.125 V", "7.250 V", "7.375 V", "7.500 V",
841*4882a593Smuzhiyun "7.625 V", "7.750 V", "7.875 V", "8.000 V",
842*4882a593Smuzhiyun "8.125 V", "8.250 V", "8.375 V", "8.500 V"
843*4882a593Smuzhiyun };
844*4882a593Smuzhiyun
845*4882a593Smuzhiyun static const struct soc_enum smart_boost_lvl_enum =
846*4882a593Smuzhiyun SOC_ENUM_SINGLE(WSA881X_BOOST_PRESET_OUT1, 0,
847*4882a593Smuzhiyun ARRAY_SIZE(smart_boost_lvl_text),
848*4882a593Smuzhiyun smart_boost_lvl_text);
849*4882a593Smuzhiyun
850*4882a593Smuzhiyun static const DECLARE_TLV_DB_SCALE(pa_gain, 0, 150, 0);
851*4882a593Smuzhiyun
852*4882a593Smuzhiyun static const struct snd_kcontrol_new wsa881x_snd_controls[] = {
853*4882a593Smuzhiyun SOC_ENUM("Smart Boost Level", smart_boost_lvl_enum),
854*4882a593Smuzhiyun WSA881X_PA_GAIN_TLV("PA Volume", WSA881X_SPKR_DRV_GAIN,
855*4882a593Smuzhiyun 4, 0xC, 1, pa_gain),
856*4882a593Smuzhiyun SOC_SINGLE_EXT("DAC Switch", WSA881X_PORT_DAC, 0, 1, 0,
857*4882a593Smuzhiyun wsa881x_get_port, wsa881x_set_port),
858*4882a593Smuzhiyun SOC_SINGLE_EXT("COMP Switch", WSA881X_PORT_COMP, 0, 1, 0,
859*4882a593Smuzhiyun wsa881x_get_port, wsa881x_set_port),
860*4882a593Smuzhiyun SOC_SINGLE_EXT("BOOST Switch", WSA881X_PORT_BOOST, 0, 1, 0,
861*4882a593Smuzhiyun wsa881x_get_port, wsa881x_set_port),
862*4882a593Smuzhiyun SOC_SINGLE_EXT("VISENSE Switch", WSA881X_PORT_VISENSE, 0, 1, 0,
863*4882a593Smuzhiyun wsa881x_get_port, wsa881x_set_port),
864*4882a593Smuzhiyun };
865*4882a593Smuzhiyun
866*4882a593Smuzhiyun static const struct snd_soc_dapm_route wsa881x_audio_map[] = {
867*4882a593Smuzhiyun { "RDAC", NULL, "IN" },
868*4882a593Smuzhiyun { "RDAC", NULL, "DCLK" },
869*4882a593Smuzhiyun { "RDAC", NULL, "ACLK" },
870*4882a593Smuzhiyun { "RDAC", NULL, "Bandgap" },
871*4882a593Smuzhiyun { "SPKR PGA", NULL, "RDAC" },
872*4882a593Smuzhiyun { "SPKR", NULL, "SPKR PGA" },
873*4882a593Smuzhiyun };
874*4882a593Smuzhiyun
wsa881x_visense_txfe_ctrl(struct snd_soc_component * comp,bool enable)875*4882a593Smuzhiyun static int wsa881x_visense_txfe_ctrl(struct snd_soc_component *comp,
876*4882a593Smuzhiyun bool enable)
877*4882a593Smuzhiyun {
878*4882a593Smuzhiyun struct wsa881x_priv *wsa881x = snd_soc_component_get_drvdata(comp);
879*4882a593Smuzhiyun
880*4882a593Smuzhiyun if (enable) {
881*4882a593Smuzhiyun regmap_multi_reg_write(wsa881x->regmap, wsa881x_vi_txfe_en_2_0,
882*4882a593Smuzhiyun ARRAY_SIZE(wsa881x_vi_txfe_en_2_0));
883*4882a593Smuzhiyun } else {
884*4882a593Smuzhiyun snd_soc_component_update_bits(comp,
885*4882a593Smuzhiyun WSA881X_SPKR_PROT_FE_VSENSE_VCM,
886*4882a593Smuzhiyun 0x08, 0x08);
887*4882a593Smuzhiyun /*
888*4882a593Smuzhiyun * 200us sleep is needed after visense txfe disable as per
889*4882a593Smuzhiyun * HW requirement.
890*4882a593Smuzhiyun */
891*4882a593Smuzhiyun usleep_range(200, 210);
892*4882a593Smuzhiyun snd_soc_component_update_bits(comp, WSA881X_SPKR_PROT_FE_GAIN,
893*4882a593Smuzhiyun 0x01, 0x00);
894*4882a593Smuzhiyun }
895*4882a593Smuzhiyun return 0;
896*4882a593Smuzhiyun }
897*4882a593Smuzhiyun
wsa881x_visense_adc_ctrl(struct snd_soc_component * comp,bool enable)898*4882a593Smuzhiyun static int wsa881x_visense_adc_ctrl(struct snd_soc_component *comp,
899*4882a593Smuzhiyun bool enable)
900*4882a593Smuzhiyun {
901*4882a593Smuzhiyun snd_soc_component_update_bits(comp, WSA881X_ADC_EN_MODU_V, BIT(7),
902*4882a593Smuzhiyun (enable << 7));
903*4882a593Smuzhiyun snd_soc_component_update_bits(comp, WSA881X_ADC_EN_MODU_I, BIT(7),
904*4882a593Smuzhiyun (enable << 7));
905*4882a593Smuzhiyun return 0;
906*4882a593Smuzhiyun }
907*4882a593Smuzhiyun
wsa881x_spkr_pa_event(struct snd_soc_dapm_widget * w,struct snd_kcontrol * kcontrol,int event)908*4882a593Smuzhiyun static int wsa881x_spkr_pa_event(struct snd_soc_dapm_widget *w,
909*4882a593Smuzhiyun struct snd_kcontrol *kcontrol, int event)
910*4882a593Smuzhiyun {
911*4882a593Smuzhiyun struct snd_soc_component *comp = snd_soc_dapm_to_component(w->dapm);
912*4882a593Smuzhiyun struct wsa881x_priv *wsa881x = snd_soc_component_get_drvdata(comp);
913*4882a593Smuzhiyun
914*4882a593Smuzhiyun switch (event) {
915*4882a593Smuzhiyun case SND_SOC_DAPM_PRE_PMU:
916*4882a593Smuzhiyun snd_soc_component_update_bits(comp, WSA881X_SPKR_OCP_CTL,
917*4882a593Smuzhiyun WSA881X_SPKR_OCP_MASK,
918*4882a593Smuzhiyun WSA881X_SPKR_OCP_EN);
919*4882a593Smuzhiyun regmap_multi_reg_write(wsa881x->regmap, wsa881x_pre_pmu_pa_2_0,
920*4882a593Smuzhiyun ARRAY_SIZE(wsa881x_pre_pmu_pa_2_0));
921*4882a593Smuzhiyun
922*4882a593Smuzhiyun snd_soc_component_update_bits(comp, WSA881X_SPKR_DRV_GAIN,
923*4882a593Smuzhiyun WSA881X_PA_GAIN_SEL_MASK,
924*4882a593Smuzhiyun WSA881X_PA_GAIN_SEL_REG);
925*4882a593Smuzhiyun break;
926*4882a593Smuzhiyun case SND_SOC_DAPM_POST_PMU:
927*4882a593Smuzhiyun if (wsa881x->port_prepared[WSA881X_PORT_VISENSE]) {
928*4882a593Smuzhiyun wsa881x_visense_txfe_ctrl(comp, true);
929*4882a593Smuzhiyun snd_soc_component_update_bits(comp,
930*4882a593Smuzhiyun WSA881X_ADC_EN_SEL_IBAIS,
931*4882a593Smuzhiyun 0x07, 0x01);
932*4882a593Smuzhiyun wsa881x_visense_adc_ctrl(comp, true);
933*4882a593Smuzhiyun }
934*4882a593Smuzhiyun
935*4882a593Smuzhiyun break;
936*4882a593Smuzhiyun case SND_SOC_DAPM_POST_PMD:
937*4882a593Smuzhiyun if (wsa881x->port_prepared[WSA881X_PORT_VISENSE]) {
938*4882a593Smuzhiyun wsa881x_visense_adc_ctrl(comp, false);
939*4882a593Smuzhiyun wsa881x_visense_txfe_ctrl(comp, false);
940*4882a593Smuzhiyun }
941*4882a593Smuzhiyun
942*4882a593Smuzhiyun snd_soc_component_update_bits(comp, WSA881X_SPKR_OCP_CTL,
943*4882a593Smuzhiyun WSA881X_SPKR_OCP_MASK,
944*4882a593Smuzhiyun WSA881X_SPKR_OCP_EN |
945*4882a593Smuzhiyun WSA881X_SPKR_OCP_HOLD);
946*4882a593Smuzhiyun break;
947*4882a593Smuzhiyun }
948*4882a593Smuzhiyun return 0;
949*4882a593Smuzhiyun }
950*4882a593Smuzhiyun
951*4882a593Smuzhiyun static const struct snd_soc_dapm_widget wsa881x_dapm_widgets[] = {
952*4882a593Smuzhiyun SND_SOC_DAPM_INPUT("IN"),
953*4882a593Smuzhiyun SND_SOC_DAPM_DAC_E("RDAC", NULL, WSA881X_SPKR_DAC_CTL, 7, 0,
954*4882a593Smuzhiyun NULL,
955*4882a593Smuzhiyun SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
956*4882a593Smuzhiyun SND_SOC_DAPM_PGA_E("SPKR PGA", SND_SOC_NOPM, 0, 0, NULL, 0,
957*4882a593Smuzhiyun wsa881x_spkr_pa_event, SND_SOC_DAPM_PRE_PMU |
958*4882a593Smuzhiyun SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
959*4882a593Smuzhiyun SND_SOC_DAPM_SUPPLY("DCLK", WSA881X_CDC_DIG_CLK_CTL, 0, 0, NULL,
960*4882a593Smuzhiyun SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
961*4882a593Smuzhiyun SND_SOC_DAPM_SUPPLY("ACLK", WSA881X_CDC_ANA_CLK_CTL, 0, 0, NULL,
962*4882a593Smuzhiyun SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
963*4882a593Smuzhiyun SND_SOC_DAPM_SUPPLY("Bandgap", WSA881X_TEMP_OP, 3, 0,
964*4882a593Smuzhiyun NULL,
965*4882a593Smuzhiyun SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
966*4882a593Smuzhiyun SND_SOC_DAPM_OUTPUT("SPKR"),
967*4882a593Smuzhiyun };
968*4882a593Smuzhiyun
wsa881x_hw_params(struct snd_pcm_substream * substream,struct snd_pcm_hw_params * params,struct snd_soc_dai * dai)969*4882a593Smuzhiyun static int wsa881x_hw_params(struct snd_pcm_substream *substream,
970*4882a593Smuzhiyun struct snd_pcm_hw_params *params,
971*4882a593Smuzhiyun struct snd_soc_dai *dai)
972*4882a593Smuzhiyun {
973*4882a593Smuzhiyun struct wsa881x_priv *wsa881x = dev_get_drvdata(dai->dev);
974*4882a593Smuzhiyun int i;
975*4882a593Smuzhiyun
976*4882a593Smuzhiyun wsa881x->active_ports = 0;
977*4882a593Smuzhiyun for (i = 0; i < WSA881X_MAX_SWR_PORTS; i++) {
978*4882a593Smuzhiyun if (!wsa881x->port_enable[i])
979*4882a593Smuzhiyun continue;
980*4882a593Smuzhiyun
981*4882a593Smuzhiyun wsa881x->port_config[wsa881x->active_ports] =
982*4882a593Smuzhiyun wsa881x_pconfig[i];
983*4882a593Smuzhiyun wsa881x->active_ports++;
984*4882a593Smuzhiyun }
985*4882a593Smuzhiyun
986*4882a593Smuzhiyun return sdw_stream_add_slave(wsa881x->slave, &wsa881x->sconfig,
987*4882a593Smuzhiyun wsa881x->port_config, wsa881x->active_ports,
988*4882a593Smuzhiyun wsa881x->sruntime);
989*4882a593Smuzhiyun }
990*4882a593Smuzhiyun
wsa881x_hw_free(struct snd_pcm_substream * substream,struct snd_soc_dai * dai)991*4882a593Smuzhiyun static int wsa881x_hw_free(struct snd_pcm_substream *substream,
992*4882a593Smuzhiyun struct snd_soc_dai *dai)
993*4882a593Smuzhiyun {
994*4882a593Smuzhiyun struct wsa881x_priv *wsa881x = dev_get_drvdata(dai->dev);
995*4882a593Smuzhiyun
996*4882a593Smuzhiyun sdw_stream_remove_slave(wsa881x->slave, wsa881x->sruntime);
997*4882a593Smuzhiyun
998*4882a593Smuzhiyun return 0;
999*4882a593Smuzhiyun }
1000*4882a593Smuzhiyun
wsa881x_set_sdw_stream(struct snd_soc_dai * dai,void * stream,int direction)1001*4882a593Smuzhiyun static int wsa881x_set_sdw_stream(struct snd_soc_dai *dai,
1002*4882a593Smuzhiyun void *stream, int direction)
1003*4882a593Smuzhiyun {
1004*4882a593Smuzhiyun struct wsa881x_priv *wsa881x = dev_get_drvdata(dai->dev);
1005*4882a593Smuzhiyun
1006*4882a593Smuzhiyun wsa881x->sruntime = stream;
1007*4882a593Smuzhiyun
1008*4882a593Smuzhiyun return 0;
1009*4882a593Smuzhiyun }
1010*4882a593Smuzhiyun
wsa881x_digital_mute(struct snd_soc_dai * dai,int mute,int stream)1011*4882a593Smuzhiyun static int wsa881x_digital_mute(struct snd_soc_dai *dai, int mute, int stream)
1012*4882a593Smuzhiyun {
1013*4882a593Smuzhiyun struct wsa881x_priv *wsa881x = dev_get_drvdata(dai->dev);
1014*4882a593Smuzhiyun
1015*4882a593Smuzhiyun if (mute)
1016*4882a593Smuzhiyun regmap_update_bits(wsa881x->regmap, WSA881X_SPKR_DRV_EN, 0x80,
1017*4882a593Smuzhiyun 0x00);
1018*4882a593Smuzhiyun else
1019*4882a593Smuzhiyun regmap_update_bits(wsa881x->regmap, WSA881X_SPKR_DRV_EN, 0x80,
1020*4882a593Smuzhiyun 0x80);
1021*4882a593Smuzhiyun
1022*4882a593Smuzhiyun return 0;
1023*4882a593Smuzhiyun }
1024*4882a593Smuzhiyun
1025*4882a593Smuzhiyun static struct snd_soc_dai_ops wsa881x_dai_ops = {
1026*4882a593Smuzhiyun .hw_params = wsa881x_hw_params,
1027*4882a593Smuzhiyun .hw_free = wsa881x_hw_free,
1028*4882a593Smuzhiyun .mute_stream = wsa881x_digital_mute,
1029*4882a593Smuzhiyun .set_sdw_stream = wsa881x_set_sdw_stream,
1030*4882a593Smuzhiyun };
1031*4882a593Smuzhiyun
1032*4882a593Smuzhiyun static struct snd_soc_dai_driver wsa881x_dais[] = {
1033*4882a593Smuzhiyun {
1034*4882a593Smuzhiyun .name = "SPKR",
1035*4882a593Smuzhiyun .id = 0,
1036*4882a593Smuzhiyun .playback = {
1037*4882a593Smuzhiyun .stream_name = "SPKR Playback",
1038*4882a593Smuzhiyun .rates = SNDRV_PCM_RATE_48000,
1039*4882a593Smuzhiyun .formats = SNDRV_PCM_FMTBIT_S16_LE,
1040*4882a593Smuzhiyun .rate_max = 48000,
1041*4882a593Smuzhiyun .rate_min = 48000,
1042*4882a593Smuzhiyun .channels_min = 1,
1043*4882a593Smuzhiyun .channels_max = 1,
1044*4882a593Smuzhiyun },
1045*4882a593Smuzhiyun .ops = &wsa881x_dai_ops,
1046*4882a593Smuzhiyun },
1047*4882a593Smuzhiyun };
1048*4882a593Smuzhiyun
1049*4882a593Smuzhiyun static const struct snd_soc_component_driver wsa881x_component_drv = {
1050*4882a593Smuzhiyun .name = "WSA881x",
1051*4882a593Smuzhiyun .probe = wsa881x_component_probe,
1052*4882a593Smuzhiyun .controls = wsa881x_snd_controls,
1053*4882a593Smuzhiyun .num_controls = ARRAY_SIZE(wsa881x_snd_controls),
1054*4882a593Smuzhiyun .dapm_widgets = wsa881x_dapm_widgets,
1055*4882a593Smuzhiyun .num_dapm_widgets = ARRAY_SIZE(wsa881x_dapm_widgets),
1056*4882a593Smuzhiyun .dapm_routes = wsa881x_audio_map,
1057*4882a593Smuzhiyun .num_dapm_routes = ARRAY_SIZE(wsa881x_audio_map),
1058*4882a593Smuzhiyun };
1059*4882a593Smuzhiyun
wsa881x_update_status(struct sdw_slave * slave,enum sdw_slave_status status)1060*4882a593Smuzhiyun static int wsa881x_update_status(struct sdw_slave *slave,
1061*4882a593Smuzhiyun enum sdw_slave_status status)
1062*4882a593Smuzhiyun {
1063*4882a593Smuzhiyun struct wsa881x_priv *wsa881x = dev_get_drvdata(&slave->dev);
1064*4882a593Smuzhiyun
1065*4882a593Smuzhiyun if (status == SDW_SLAVE_ATTACHED && slave->dev_num > 0)
1066*4882a593Smuzhiyun wsa881x_init(wsa881x);
1067*4882a593Smuzhiyun
1068*4882a593Smuzhiyun return 0;
1069*4882a593Smuzhiyun }
1070*4882a593Smuzhiyun
wsa881x_port_prep(struct sdw_slave * slave,struct sdw_prepare_ch * prepare_ch,enum sdw_port_prep_ops state)1071*4882a593Smuzhiyun static int wsa881x_port_prep(struct sdw_slave *slave,
1072*4882a593Smuzhiyun struct sdw_prepare_ch *prepare_ch,
1073*4882a593Smuzhiyun enum sdw_port_prep_ops state)
1074*4882a593Smuzhiyun {
1075*4882a593Smuzhiyun struct wsa881x_priv *wsa881x = dev_get_drvdata(&slave->dev);
1076*4882a593Smuzhiyun
1077*4882a593Smuzhiyun if (state == SDW_OPS_PORT_POST_PREP)
1078*4882a593Smuzhiyun wsa881x->port_prepared[prepare_ch->num - 1] = true;
1079*4882a593Smuzhiyun else
1080*4882a593Smuzhiyun wsa881x->port_prepared[prepare_ch->num - 1] = false;
1081*4882a593Smuzhiyun
1082*4882a593Smuzhiyun return 0;
1083*4882a593Smuzhiyun }
1084*4882a593Smuzhiyun
wsa881x_bus_config(struct sdw_slave * slave,struct sdw_bus_params * params)1085*4882a593Smuzhiyun static int wsa881x_bus_config(struct sdw_slave *slave,
1086*4882a593Smuzhiyun struct sdw_bus_params *params)
1087*4882a593Smuzhiyun {
1088*4882a593Smuzhiyun sdw_write(slave, SWRS_SCP_HOST_CLK_DIV2_CTL_BANK(params->next_bank),
1089*4882a593Smuzhiyun 0x01);
1090*4882a593Smuzhiyun
1091*4882a593Smuzhiyun return 0;
1092*4882a593Smuzhiyun }
1093*4882a593Smuzhiyun
1094*4882a593Smuzhiyun static struct sdw_slave_ops wsa881x_slave_ops = {
1095*4882a593Smuzhiyun .update_status = wsa881x_update_status,
1096*4882a593Smuzhiyun .bus_config = wsa881x_bus_config,
1097*4882a593Smuzhiyun .port_prep = wsa881x_port_prep,
1098*4882a593Smuzhiyun };
1099*4882a593Smuzhiyun
wsa881x_probe(struct sdw_slave * pdev,const struct sdw_device_id * id)1100*4882a593Smuzhiyun static int wsa881x_probe(struct sdw_slave *pdev,
1101*4882a593Smuzhiyun const struct sdw_device_id *id)
1102*4882a593Smuzhiyun {
1103*4882a593Smuzhiyun struct wsa881x_priv *wsa881x;
1104*4882a593Smuzhiyun
1105*4882a593Smuzhiyun wsa881x = devm_kzalloc(&pdev->dev, sizeof(*wsa881x), GFP_KERNEL);
1106*4882a593Smuzhiyun if (!wsa881x)
1107*4882a593Smuzhiyun return -ENOMEM;
1108*4882a593Smuzhiyun
1109*4882a593Smuzhiyun wsa881x->sd_n = devm_gpiod_get_optional(&pdev->dev, "powerdown",
1110*4882a593Smuzhiyun GPIOD_FLAGS_BIT_NONEXCLUSIVE);
1111*4882a593Smuzhiyun if (IS_ERR(wsa881x->sd_n)) {
1112*4882a593Smuzhiyun dev_err(&pdev->dev, "Shutdown Control GPIO not found\n");
1113*4882a593Smuzhiyun return PTR_ERR(wsa881x->sd_n);
1114*4882a593Smuzhiyun }
1115*4882a593Smuzhiyun
1116*4882a593Smuzhiyun dev_set_drvdata(&pdev->dev, wsa881x);
1117*4882a593Smuzhiyun wsa881x->slave = pdev;
1118*4882a593Smuzhiyun wsa881x->dev = &pdev->dev;
1119*4882a593Smuzhiyun wsa881x->sconfig.ch_count = 1;
1120*4882a593Smuzhiyun wsa881x->sconfig.bps = 1;
1121*4882a593Smuzhiyun wsa881x->sconfig.frame_rate = 48000;
1122*4882a593Smuzhiyun wsa881x->sconfig.direction = SDW_DATA_DIR_RX;
1123*4882a593Smuzhiyun wsa881x->sconfig.type = SDW_STREAM_PDM;
1124*4882a593Smuzhiyun pdev->prop.sink_ports = GENMASK(WSA881X_MAX_SWR_PORTS, 0);
1125*4882a593Smuzhiyun pdev->prop.sink_dpn_prop = wsa_sink_dpn_prop;
1126*4882a593Smuzhiyun pdev->prop.scp_int1_mask = SDW_SCP_INT1_BUS_CLASH | SDW_SCP_INT1_PARITY;
1127*4882a593Smuzhiyun gpiod_direction_output(wsa881x->sd_n, 1);
1128*4882a593Smuzhiyun
1129*4882a593Smuzhiyun wsa881x->regmap = devm_regmap_init_sdw(pdev, &wsa881x_regmap_config);
1130*4882a593Smuzhiyun if (IS_ERR(wsa881x->regmap)) {
1131*4882a593Smuzhiyun dev_err(&pdev->dev, "regmap_init failed\n");
1132*4882a593Smuzhiyun return PTR_ERR(wsa881x->regmap);
1133*4882a593Smuzhiyun }
1134*4882a593Smuzhiyun
1135*4882a593Smuzhiyun return devm_snd_soc_register_component(&pdev->dev,
1136*4882a593Smuzhiyun &wsa881x_component_drv,
1137*4882a593Smuzhiyun wsa881x_dais,
1138*4882a593Smuzhiyun ARRAY_SIZE(wsa881x_dais));
1139*4882a593Smuzhiyun }
1140*4882a593Smuzhiyun
1141*4882a593Smuzhiyun static const struct sdw_device_id wsa881x_slave_id[] = {
1142*4882a593Smuzhiyun SDW_SLAVE_ENTRY(0x0217, 0x2010, 0),
1143*4882a593Smuzhiyun SDW_SLAVE_ENTRY(0x0217, 0x2110, 0),
1144*4882a593Smuzhiyun {},
1145*4882a593Smuzhiyun };
1146*4882a593Smuzhiyun MODULE_DEVICE_TABLE(sdw, wsa881x_slave_id);
1147*4882a593Smuzhiyun
1148*4882a593Smuzhiyun static struct sdw_driver wsa881x_codec_driver = {
1149*4882a593Smuzhiyun .probe = wsa881x_probe,
1150*4882a593Smuzhiyun .ops = &wsa881x_slave_ops,
1151*4882a593Smuzhiyun .id_table = wsa881x_slave_id,
1152*4882a593Smuzhiyun .driver = {
1153*4882a593Smuzhiyun .name = "wsa881x-codec",
1154*4882a593Smuzhiyun }
1155*4882a593Smuzhiyun };
1156*4882a593Smuzhiyun module_sdw_driver(wsa881x_codec_driver);
1157*4882a593Smuzhiyun
1158*4882a593Smuzhiyun MODULE_DESCRIPTION("WSA881x codec driver");
1159*4882a593Smuzhiyun MODULE_LICENSE("GPL v2");
1160