1 | // SPDX-License-Identifier: GPL-2.0 |
2 | // Copyright (c) 2022, Analog Devices Inc. |
3 | |
4 | #include <linux/gpio/consumer.h> |
5 | #include <linux/i2c.h> |
6 | #include <linux/module.h> |
7 | #include <sound/pcm_params.h> |
8 | #include <linux/regulator/consumer.h> |
9 | #include <sound/soc.h> |
10 | #include <sound/tlv.h> |
11 | #include "max98396.h" |
12 | |
13 | static const char * const max98396_core_supplies[MAX98396_NUM_CORE_SUPPLIES] = { |
14 | "avdd" , |
15 | "dvdd" , |
16 | "dvddio" , |
17 | }; |
18 | |
19 | static struct reg_default max98396_reg[] = { |
20 | {MAX98396_R2000_SW_RESET, 0x00}, |
21 | {MAX98396_R2001_INT_RAW1, 0x00}, |
22 | {MAX98396_R2002_INT_RAW2, 0x00}, |
23 | {MAX98396_R2003_INT_RAW3, 0x00}, |
24 | {MAX98396_R2004_INT_RAW4, 0x00}, |
25 | {MAX98396_R2006_INT_STATE1, 0x00}, |
26 | {MAX98396_R2007_INT_STATE2, 0x00}, |
27 | {MAX98396_R2008_INT_STATE3, 0x00}, |
28 | {MAX98396_R2009_INT_STATE4, 0x00}, |
29 | {MAX98396_R200B_INT_FLAG1, 0x00}, |
30 | {MAX98396_R200C_INT_FLAG2, 0x00}, |
31 | {MAX98396_R200D_INT_FLAG3, 0x00}, |
32 | {MAX98396_R200E_INT_FLAG4, 0x00}, |
33 | {MAX98396_R2010_INT_EN1, 0x02}, |
34 | {MAX98396_R2011_INT_EN2, 0x00}, |
35 | {MAX98396_R2012_INT_EN3, 0x00}, |
36 | {MAX98396_R2013_INT_EN4, 0x00}, |
37 | {MAX98396_R2015_INT_FLAG_CLR1, 0x00}, |
38 | {MAX98396_R2016_INT_FLAG_CLR2, 0x00}, |
39 | {MAX98396_R2017_INT_FLAG_CLR3, 0x00}, |
40 | {MAX98396_R2018_INT_FLAG_CLR4, 0x00}, |
41 | {MAX98396_R201F_IRQ_CTRL, 0x00}, |
42 | {MAX98396_R2020_THERM_WARN_THRESH, 0x46}, |
43 | {MAX98396_R2021_THERM_WARN_THRESH2, 0x46}, |
44 | {MAX98396_R2022_THERM_SHDN_THRESH, 0x64}, |
45 | {MAX98396_R2023_THERM_HYSTERESIS, 0x02}, |
46 | {MAX98396_R2024_THERM_FOLDBACK_SET, 0xC5}, |
47 | {MAX98396_R2027_THERM_FOLDBACK_EN, 0x01}, |
48 | {MAX98396_R2030_NOISEGATE_MODE_CTRL, 0x32}, |
49 | {MAX98396_R2033_NOISEGATE_MODE_EN, 0x00}, |
50 | {MAX98396_R2038_CLK_MON_CTRL, 0x00}, |
51 | {MAX98396_R2039_DATA_MON_CTRL, 0x00}, |
52 | {MAX98396_R203F_ENABLE_CTRLS, 0x0F}, |
53 | {MAX98396_R2040_PIN_CFG, 0x55}, |
54 | {MAX98396_R2041_PCM_MODE_CFG, 0xC0}, |
55 | {MAX98396_R2042_PCM_CLK_SETUP, 0x04}, |
56 | {MAX98396_R2043_PCM_SR_SETUP, 0x88}, |
57 | {MAX98396_R2044_PCM_TX_CTRL_1, 0x00}, |
58 | {MAX98396_R2045_PCM_TX_CTRL_2, 0x00}, |
59 | {MAX98396_R2046_PCM_TX_CTRL_3, 0x00}, |
60 | {MAX98396_R2047_PCM_TX_CTRL_4, 0x00}, |
61 | {MAX98396_R2048_PCM_TX_CTRL_5, 0x00}, |
62 | {MAX98396_R2049_PCM_TX_CTRL_6, 0x00}, |
63 | {MAX98396_R204A_PCM_TX_CTRL_7, 0x00}, |
64 | {MAX98396_R204B_PCM_TX_CTRL_8, 0x00}, |
65 | {MAX98396_R204C_PCM_TX_HIZ_CTRL_1, 0xFF}, |
66 | {MAX98396_R204D_PCM_TX_HIZ_CTRL_2, 0xFF}, |
67 | {MAX98396_R204E_PCM_TX_HIZ_CTRL_3, 0xFF}, |
68 | {MAX98396_R204F_PCM_TX_HIZ_CTRL_4, 0xFF}, |
69 | {MAX98396_R2050_PCM_TX_HIZ_CTRL_5, 0xFF}, |
70 | {MAX98396_R2051_PCM_TX_HIZ_CTRL_6, 0xFF}, |
71 | {MAX98396_R2052_PCM_TX_HIZ_CTRL_7, 0xFF}, |
72 | {MAX98396_R2053_PCM_TX_HIZ_CTRL_8, 0xFF}, |
73 | {MAX98396_R2055_PCM_RX_SRC1, 0x00}, |
74 | {MAX98396_R2056_PCM_RX_SRC2, 0x00}, |
75 | {MAX98396_R2058_PCM_BYPASS_SRC, 0x00}, |
76 | {MAX98396_R205D_PCM_TX_SRC_EN, 0x00}, |
77 | {MAX98396_R205E_PCM_RX_EN, 0x00}, |
78 | {MAX98396_R205F_PCM_TX_EN, 0x00}, |
79 | {MAX98396_R2070_ICC_RX_EN_A, 0x00}, |
80 | {MAX98396_R2071_ICC_RX_EN_B, 0x00}, |
81 | {MAX98396_R2072_ICC_TX_CTRL, 0x00}, |
82 | {MAX98396_R207F_ICC_EN, 0x00}, |
83 | {MAX98396_R2083_TONE_GEN_DC_CFG, 0x04}, |
84 | {MAX98396_R2084_TONE_GEN_DC_LVL1, 0x00}, |
85 | {MAX98396_R2085_TONE_GEN_DC_LVL2, 0x00}, |
86 | {MAX98396_R2086_TONE_GEN_DC_LVL3, 0x00}, |
87 | {MAX98396_R208F_TONE_GEN_EN, 0x00}, |
88 | {MAX98396_R2090_AMP_VOL_CTRL, 0x00}, |
89 | {MAX98396_R2091_AMP_PATH_GAIN, 0x0B}, |
90 | {MAX98396_R2092_AMP_DSP_CFG, 0x23}, |
91 | {MAX98396_R2093_SSM_CFG, 0x0D}, |
92 | {MAX98396_R2094_SPK_CLS_DG_THRESH, 0x12}, |
93 | {MAX98396_R2095_SPK_CLS_DG_HDR, 0x17}, |
94 | {MAX98396_R2096_SPK_CLS_DG_HOLD_TIME, 0x17}, |
95 | {MAX98396_R2097_SPK_CLS_DG_DELAY, 0x00}, |
96 | {MAX98396_R2098_SPK_CLS_DG_MODE, 0x00}, |
97 | {MAX98396_R2099_SPK_CLS_DG_VBAT_LVL, 0x03}, |
98 | {MAX98396_R209A_SPK_EDGE_CTRL, 0x00}, |
99 | {MAX98396_R209C_SPK_EDGE_CTRL1, 0x0A}, |
100 | {MAX98396_R209D_SPK_EDGE_CTRL2, 0xAA}, |
101 | {MAX98396_R209E_AMP_CLIP_GAIN, 0x00}, |
102 | {MAX98396_R209F_BYPASS_PATH_CFG, 0x00}, |
103 | {MAX98396_R20A0_AMP_SUPPLY_CTL, 0x00}, |
104 | {MAX98396_R20AF_AMP_EN, 0x00}, |
105 | {MAX98396_R20B0_ADC_SR, 0x30}, |
106 | {MAX98396_R20B1_ADC_PVDD_CFG, 0x00}, |
107 | {MAX98396_R20B2_ADC_VBAT_CFG, 0x00}, |
108 | {MAX98396_R20B3_ADC_THERMAL_CFG, 0x00}, |
109 | {MAX98396_R20B4_ADC_READBACK_CTRL1, 0x00}, |
110 | {MAX98396_R20B5_ADC_READBACK_CTRL2, 0x00}, |
111 | {MAX98396_R20B6_ADC_PVDD_READBACK_MSB, 0x00}, |
112 | {MAX98396_R20B7_ADC_PVDD_READBACK_LSB, 0x00}, |
113 | {MAX98396_R20B8_ADC_VBAT_READBACK_MSB, 0x00}, |
114 | {MAX98396_R20B9_ADC_VBAT_READBACK_LSB, 0x00}, |
115 | {MAX98396_R20BA_ADC_TEMP_READBACK_MSB, 0x00}, |
116 | {MAX98396_R20BB_ADC_TEMP_READBACK_LSB, 0x00}, |
117 | {MAX98396_R20BC_ADC_LO_PVDD_READBACK_MSB, 0x00}, |
118 | {MAX98396_R20BD_ADC_LO_PVDD_READBACK_LSB, 0x00}, |
119 | {MAX98396_R20BE_ADC_LO_VBAT_READBACK_MSB, 0x00}, |
120 | {MAX98396_R20BF_ADC_LO_VBAT_READBACK_LSB, 0x00}, |
121 | {MAX98396_R20C7_ADC_CFG, 0x00}, |
122 | {MAX98396_R20D0_DHT_CFG1, 0x00}, |
123 | {MAX98396_R20D1_LIMITER_CFG1, 0x08}, |
124 | {MAX98396_R20D2_LIMITER_CFG2, 0x00}, |
125 | {MAX98396_R20D3_DHT_CFG2, 0x14}, |
126 | {MAX98396_R20D4_DHT_CFG3, 0x02}, |
127 | {MAX98396_R20D5_DHT_CFG4, 0x04}, |
128 | {MAX98396_R20D6_DHT_HYSTERESIS_CFG, 0x07}, |
129 | {MAX98396_R20DF_DHT_EN, 0x00}, |
130 | {MAX98396_R20E0_IV_SENSE_PATH_CFG, 0x04}, |
131 | {MAX98396_R20E4_IV_SENSE_PATH_EN, 0x00}, |
132 | {MAX98396_R20E5_BPE_STATE, 0x00}, |
133 | {MAX98396_R20E6_BPE_L3_THRESH_MSB, 0x00}, |
134 | {MAX98396_R20E7_BPE_L3_THRESH_LSB, 0x00}, |
135 | {MAX98396_R20E8_BPE_L2_THRESH_MSB, 0x00}, |
136 | {MAX98396_R20E9_BPE_L2_THRESH_LSB, 0x00}, |
137 | {MAX98396_R20EA_BPE_L1_THRESH_MSB, 0x00}, |
138 | {MAX98396_R20EB_BPE_L1_THRESH_LSB, 0x00}, |
139 | {MAX98396_R20EC_BPE_L0_THRESH_MSB, 0x00}, |
140 | {MAX98396_R20ED_BPE_L0_THRESH_LSB, 0x00}, |
141 | {MAX98396_R20EE_BPE_L3_DWELL_HOLD_TIME, 0x00}, |
142 | {MAX98396_R20EF_BPE_L2_DWELL_HOLD_TIME, 0x00}, |
143 | {MAX98396_R20F0_BPE_L1_DWELL_HOLD_TIME, 0x00}, |
144 | {MAX98396_R20F1_BPE_L0_HOLD_TIME, 0x00}, |
145 | {MAX98396_R20F2_BPE_L3_ATTACK_REL_STEP, 0x00}, |
146 | {MAX98396_R20F3_BPE_L2_ATTACK_REL_STEP, 0x00}, |
147 | {MAX98396_R20F4_BPE_L1_ATTACK_REL_STEP, 0x00}, |
148 | {MAX98396_R20F5_BPE_L0_ATTACK_REL_STEP, 0x00}, |
149 | {MAX98396_R20F6_BPE_L3_MAX_GAIN_ATTN, 0x00}, |
150 | {MAX98396_R20F7_BPE_L2_MAX_GAIN_ATTN, 0x00}, |
151 | {MAX98396_R20F8_BPE_L1_MAX_GAIN_ATTN, 0x00}, |
152 | {MAX98396_R20F9_BPE_L0_MAX_GAIN_ATTN, 0x00}, |
153 | {MAX98396_R20FA_BPE_L3_ATT_REL_RATE, 0x00}, |
154 | {MAX98396_R20FB_BPE_L2_ATT_REL_RATE, 0x00}, |
155 | {MAX98396_R20FC_BPE_L1_ATT_REL_RATE, 0x00}, |
156 | {MAX98396_R20FD_BPE_L0_ATT_REL_RATE, 0x00}, |
157 | {MAX98396_R20FE_BPE_L3_LIMITER_CFG, 0x00}, |
158 | {MAX98396_R20FF_BPE_L2_LIMITER_CFG, 0x00}, |
159 | {MAX98396_R2100_BPE_L1_LIMITER_CFG, 0x00}, |
160 | {MAX98396_R2101_BPE_L0_LIMITER_CFG, 0x00}, |
161 | {MAX98396_R2102_BPE_L3_LIM_ATT_REL_RATE, 0x00}, |
162 | {MAX98396_R2103_BPE_L2_LIM_ATT_REL_RATE, 0x00}, |
163 | {MAX98396_R2104_BPE_L1_LIM_ATT_REL_RATE, 0x00}, |
164 | {MAX98396_R2105_BPE_L0_LIM_ATT_REL_RATE, 0x00}, |
165 | {MAX98396_R2106_BPE_THRESH_HYSTERESIS, 0x00}, |
166 | {MAX98396_R2107_BPE_INFINITE_HOLD_CLR, 0x00}, |
167 | {MAX98396_R2108_BPE_SUPPLY_SRC, 0x00}, |
168 | {MAX98396_R2109_BPE_LOW_STATE, 0x00}, |
169 | {MAX98396_R210A_BPE_LOW_GAIN, 0x00}, |
170 | {MAX98396_R210B_BPE_LOW_LIMITER, 0x00}, |
171 | {MAX98396_R210D_BPE_EN, 0x00}, |
172 | {MAX98396_R210E_AUTO_RESTART, 0x00}, |
173 | {MAX98396_R210F_GLOBAL_EN, 0x00}, |
174 | {MAX98396_R21FF_REVISION_ID, 0x00}, |
175 | }; |
176 | |
177 | static struct reg_default max98397_reg[] = { |
178 | {MAX98396_R2000_SW_RESET, 0x00}, |
179 | {MAX98396_R2001_INT_RAW1, 0x00}, |
180 | {MAX98396_R2002_INT_RAW2, 0x00}, |
181 | {MAX98396_R2003_INT_RAW3, 0x00}, |
182 | {MAX98396_R2004_INT_RAW4, 0x00}, |
183 | {MAX98396_R2006_INT_STATE1, 0x00}, |
184 | {MAX98396_R2007_INT_STATE2, 0x00}, |
185 | {MAX98396_R2008_INT_STATE3, 0x00}, |
186 | {MAX98396_R2009_INT_STATE4, 0x00}, |
187 | {MAX98396_R200B_INT_FLAG1, 0x00}, |
188 | {MAX98396_R200C_INT_FLAG2, 0x00}, |
189 | {MAX98396_R200D_INT_FLAG3, 0x00}, |
190 | {MAX98396_R200E_INT_FLAG4, 0x00}, |
191 | {MAX98396_R2010_INT_EN1, 0x02}, |
192 | {MAX98396_R2011_INT_EN2, 0x00}, |
193 | {MAX98396_R2012_INT_EN3, 0x00}, |
194 | {MAX98396_R2013_INT_EN4, 0x00}, |
195 | {MAX98396_R2015_INT_FLAG_CLR1, 0x00}, |
196 | {MAX98396_R2016_INT_FLAG_CLR2, 0x00}, |
197 | {MAX98396_R2017_INT_FLAG_CLR3, 0x00}, |
198 | {MAX98396_R2018_INT_FLAG_CLR4, 0x00}, |
199 | {MAX98396_R201F_IRQ_CTRL, 0x00}, |
200 | {MAX98396_R2020_THERM_WARN_THRESH, 0x46}, |
201 | {MAX98396_R2021_THERM_WARN_THRESH2, 0x46}, |
202 | {MAX98396_R2022_THERM_SHDN_THRESH, 0x64}, |
203 | {MAX98396_R2023_THERM_HYSTERESIS, 0x02}, |
204 | {MAX98396_R2024_THERM_FOLDBACK_SET, 0xC5}, |
205 | {MAX98396_R2027_THERM_FOLDBACK_EN, 0x01}, |
206 | {MAX98396_R2030_NOISEGATE_MODE_CTRL, 0x32}, |
207 | {MAX98396_R2033_NOISEGATE_MODE_EN, 0x00}, |
208 | {MAX98396_R2038_CLK_MON_CTRL, 0x00}, |
209 | {MAX98396_R2039_DATA_MON_CTRL, 0x00}, |
210 | {MAX98397_R203A_SPK_MON_THRESH, 0x03}, |
211 | {MAX98396_R203F_ENABLE_CTRLS, 0x0F}, |
212 | {MAX98396_R2040_PIN_CFG, 0x55}, |
213 | {MAX98396_R2041_PCM_MODE_CFG, 0xC0}, |
214 | {MAX98396_R2042_PCM_CLK_SETUP, 0x04}, |
215 | {MAX98396_R2043_PCM_SR_SETUP, 0x88}, |
216 | {MAX98396_R2044_PCM_TX_CTRL_1, 0x00}, |
217 | {MAX98396_R2045_PCM_TX_CTRL_2, 0x00}, |
218 | {MAX98396_R2046_PCM_TX_CTRL_3, 0x00}, |
219 | {MAX98396_R2047_PCM_TX_CTRL_4, 0x00}, |
220 | {MAX98396_R2048_PCM_TX_CTRL_5, 0x00}, |
221 | {MAX98396_R2049_PCM_TX_CTRL_6, 0x00}, |
222 | {MAX98396_R204A_PCM_TX_CTRL_7, 0x00}, |
223 | {MAX98396_R204B_PCM_TX_CTRL_8, 0x00}, |
224 | {MAX98397_R204C_PCM_TX_CTRL_9, 0x00}, |
225 | {MAX98397_R204D_PCM_TX_HIZ_CTRL_1, 0xFF}, |
226 | {MAX98397_R204E_PCM_TX_HIZ_CTRL_2, 0xFF}, |
227 | {MAX98397_R204F_PCM_TX_HIZ_CTRL_3, 0xFF}, |
228 | {MAX98397_R2050_PCM_TX_HIZ_CTRL_4, 0xFF}, |
229 | {MAX98397_R2051_PCM_TX_HIZ_CTRL_5, 0xFF}, |
230 | {MAX98397_R2052_PCM_TX_HIZ_CTRL_6, 0xFF}, |
231 | {MAX98397_R2053_PCM_TX_HIZ_CTRL_7, 0xFF}, |
232 | {MAX98397_R2054_PCM_TX_HIZ_CTRL_8, 0xFF}, |
233 | {MAX98397_R2056_PCM_RX_SRC1, 0x00}, |
234 | {MAX98397_R2057_PCM_RX_SRC2, 0x00}, |
235 | {MAX98396_R2058_PCM_BYPASS_SRC, 0x00}, |
236 | {MAX98396_R205D_PCM_TX_SRC_EN, 0x00}, |
237 | {MAX98396_R205E_PCM_RX_EN, 0x00}, |
238 | {MAX98396_R205F_PCM_TX_EN, 0x00}, |
239 | {MAX98397_R2060_PCM_TX_SUPPLY_SEL, 0x00}, |
240 | {MAX98396_R2070_ICC_RX_EN_A, 0x00}, |
241 | {MAX98396_R2071_ICC_RX_EN_B, 0x00}, |
242 | {MAX98396_R2072_ICC_TX_CTRL, 0x00}, |
243 | {MAX98396_R207F_ICC_EN, 0x00}, |
244 | {MAX98396_R2083_TONE_GEN_DC_CFG, 0x04}, |
245 | {MAX98396_R2084_TONE_GEN_DC_LVL1, 0x00}, |
246 | {MAX98396_R2085_TONE_GEN_DC_LVL2, 0x00}, |
247 | {MAX98396_R2086_TONE_GEN_DC_LVL3, 0x00}, |
248 | {MAX98396_R208F_TONE_GEN_EN, 0x00}, |
249 | {MAX98396_R2090_AMP_VOL_CTRL, 0x00}, |
250 | {MAX98396_R2091_AMP_PATH_GAIN, 0x12}, |
251 | {MAX98396_R2092_AMP_DSP_CFG, 0x22}, |
252 | {MAX98396_R2093_SSM_CFG, 0x08}, |
253 | {MAX98396_R2094_SPK_CLS_DG_THRESH, 0x12}, |
254 | {MAX98396_R2095_SPK_CLS_DG_HDR, 0x17}, |
255 | {MAX98396_R2096_SPK_CLS_DG_HOLD_TIME, 0x17}, |
256 | {MAX98396_R2097_SPK_CLS_DG_DELAY, 0x00}, |
257 | {MAX98396_R2098_SPK_CLS_DG_MODE, 0x00}, |
258 | {MAX98396_R2099_SPK_CLS_DG_VBAT_LVL, 0x03}, |
259 | {MAX98396_R209A_SPK_EDGE_CTRL, 0x00}, |
260 | {MAX98397_R209B_SPK_PATH_WB_ONLY, 0x00}, |
261 | {MAX98396_R209C_SPK_EDGE_CTRL1, 0x03}, |
262 | {MAX98396_R209D_SPK_EDGE_CTRL2, 0xFC}, |
263 | {MAX98396_R209E_AMP_CLIP_GAIN, 0x00}, |
264 | {MAX98396_R209F_BYPASS_PATH_CFG, 0x00}, |
265 | {MAX98396_R20AF_AMP_EN, 0x00}, |
266 | {MAX98396_R20B0_ADC_SR, 0x30}, |
267 | {MAX98396_R20B1_ADC_PVDD_CFG, 0x00}, |
268 | {MAX98396_R20B2_ADC_VBAT_CFG, 0x00}, |
269 | {MAX98396_R20B3_ADC_THERMAL_CFG, 0x00}, |
270 | {MAX98397_R20B4_ADC_VDDH_CFG, 0x00}, |
271 | {MAX98397_R20B5_ADC_READBACK_CTRL1, 0x00}, |
272 | {MAX98397_R20B6_ADC_READBACK_CTRL2, 0x00}, |
273 | {MAX98397_R20B7_ADC_PVDD_READBACK_MSB, 0x00}, |
274 | {MAX98397_R20B8_ADC_PVDD_READBACK_LSB, 0x00}, |
275 | {MAX98397_R20B9_ADC_VBAT_READBACK_MSB, 0x00}, |
276 | {MAX98397_R20BA_ADC_VBAT_READBACK_LSB, 0x00}, |
277 | {MAX98397_R20BB_ADC_TEMP_READBACK_MSB, 0x00}, |
278 | {MAX98397_R20BC_ADC_TEMP_READBACK_LSB, 0x00}, |
279 | {MAX98397_R20BD_ADC_VDDH__READBACK_MSB, 0x00}, |
280 | {MAX98397_R20BE_ADC_VDDH_READBACK_LSB, 0x00}, |
281 | {MAX98396_R20BF_ADC_LO_VBAT_READBACK_LSB, 0x00}, |
282 | {MAX98397_R20C3_ADC_LO_VDDH_READBACK_MSB, 0x00}, |
283 | {MAX98397_R20C4_ADC_LO_VDDH_READBACK_LSB, 0x00}, |
284 | {MAX98397_R20C5_MEAS_ADC_OPTIMAL_MODE, 0x04}, |
285 | {MAX98396_R20C7_ADC_CFG, 0x00}, |
286 | {MAX98396_R20D0_DHT_CFG1, 0x00}, |
287 | {MAX98396_R20D1_LIMITER_CFG1, 0x08}, |
288 | {MAX98396_R20D2_LIMITER_CFG2, 0x00}, |
289 | {MAX98396_R20D3_DHT_CFG2, 0x14}, |
290 | {MAX98396_R20D4_DHT_CFG3, 0x02}, |
291 | {MAX98396_R20D5_DHT_CFG4, 0x04}, |
292 | {MAX98396_R20D6_DHT_HYSTERESIS_CFG, 0x07}, |
293 | {MAX98396_R20DF_DHT_EN, 0x00}, |
294 | {MAX98396_R20E0_IV_SENSE_PATH_CFG, 0x04}, |
295 | {MAX98396_R20E4_IV_SENSE_PATH_EN, 0x00}, |
296 | {MAX98396_R20E5_BPE_STATE, 0x00}, |
297 | {MAX98396_R20E6_BPE_L3_THRESH_MSB, 0x00}, |
298 | {MAX98396_R20E7_BPE_L3_THRESH_LSB, 0x00}, |
299 | {MAX98396_R20E8_BPE_L2_THRESH_MSB, 0x00}, |
300 | {MAX98396_R20E9_BPE_L2_THRESH_LSB, 0x00}, |
301 | {MAX98396_R20EA_BPE_L1_THRESH_MSB, 0x00}, |
302 | {MAX98396_R20EB_BPE_L1_THRESH_LSB, 0x00}, |
303 | {MAX98396_R20EC_BPE_L0_THRESH_MSB, 0x00}, |
304 | {MAX98396_R20ED_BPE_L0_THRESH_LSB, 0x00}, |
305 | {MAX98396_R20EE_BPE_L3_DWELL_HOLD_TIME, 0x00}, |
306 | {MAX98396_R20EF_BPE_L2_DWELL_HOLD_TIME, 0x00}, |
307 | {MAX98396_R20F0_BPE_L1_DWELL_HOLD_TIME, 0x00}, |
308 | {MAX98396_R20F1_BPE_L0_HOLD_TIME, 0x00}, |
309 | {MAX98396_R20F2_BPE_L3_ATTACK_REL_STEP, 0x00}, |
310 | {MAX98396_R20F3_BPE_L2_ATTACK_REL_STEP, 0x00}, |
311 | {MAX98396_R20F4_BPE_L1_ATTACK_REL_STEP, 0x00}, |
312 | {MAX98396_R20F5_BPE_L0_ATTACK_REL_STEP, 0x00}, |
313 | {MAX98396_R20F6_BPE_L3_MAX_GAIN_ATTN, 0x00}, |
314 | {MAX98396_R20F7_BPE_L2_MAX_GAIN_ATTN, 0x00}, |
315 | {MAX98396_R20F8_BPE_L1_MAX_GAIN_ATTN, 0x00}, |
316 | {MAX98396_R20F9_BPE_L0_MAX_GAIN_ATTN, 0x00}, |
317 | {MAX98396_R20FA_BPE_L3_ATT_REL_RATE, 0x00}, |
318 | {MAX98396_R20FB_BPE_L2_ATT_REL_RATE, 0x00}, |
319 | {MAX98396_R20FC_BPE_L1_ATT_REL_RATE, 0x00}, |
320 | {MAX98396_R20FD_BPE_L0_ATT_REL_RATE, 0x00}, |
321 | {MAX98396_R20FE_BPE_L3_LIMITER_CFG, 0x00}, |
322 | {MAX98396_R20FF_BPE_L2_LIMITER_CFG, 0x00}, |
323 | {MAX98396_R2100_BPE_L1_LIMITER_CFG, 0x00}, |
324 | {MAX98396_R2101_BPE_L0_LIMITER_CFG, 0x00}, |
325 | {MAX98396_R2102_BPE_L3_LIM_ATT_REL_RATE, 0x00}, |
326 | {MAX98396_R2103_BPE_L2_LIM_ATT_REL_RATE, 0x00}, |
327 | {MAX98396_R2104_BPE_L1_LIM_ATT_REL_RATE, 0x00}, |
328 | {MAX98396_R2105_BPE_L0_LIM_ATT_REL_RATE, 0x00}, |
329 | {MAX98396_R2106_BPE_THRESH_HYSTERESIS, 0x00}, |
330 | {MAX98396_R2107_BPE_INFINITE_HOLD_CLR, 0x00}, |
331 | {MAX98396_R2108_BPE_SUPPLY_SRC, 0x00}, |
332 | {MAX98396_R2109_BPE_LOW_STATE, 0x00}, |
333 | {MAX98396_R210A_BPE_LOW_GAIN, 0x00}, |
334 | {MAX98396_R210B_BPE_LOW_LIMITER, 0x00}, |
335 | {MAX98396_R210D_BPE_EN, 0x00}, |
336 | {MAX98396_R210E_AUTO_RESTART, 0x00}, |
337 | {MAX98396_R210F_GLOBAL_EN, 0x00}, |
338 | {MAX98397_R22FF_REVISION_ID, 0x00}, |
339 | }; |
340 | |
341 | static void max98396_global_enable_onoff(struct regmap *regmap, bool onoff) |
342 | { |
343 | regmap_write(map: regmap, MAX98396_R210F_GLOBAL_EN, val: onoff ? 1 : 0); |
344 | usleep_range(min: 11000, max: 12000); |
345 | } |
346 | |
347 | static int max98396_dai_set_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) |
348 | { |
349 | struct snd_soc_component *component = codec_dai->component; |
350 | struct max98396_priv *max98396 = snd_soc_component_get_drvdata(c: component); |
351 | unsigned int format_mask, format = 0; |
352 | unsigned int bclk_pol = 0; |
353 | int ret, status; |
354 | int reg; |
355 | bool update = false; |
356 | |
357 | format_mask = MAX98396_PCM_MODE_CFG_FORMAT_MASK | |
358 | MAX98396_PCM_MODE_CFG_LRCLKEDGE; |
359 | |
360 | dev_dbg(component->dev, "%s: fmt 0x%08X\n" , __func__, fmt); |
361 | |
362 | switch (fmt & SND_SOC_DAIFMT_INV_MASK) { |
363 | case SND_SOC_DAIFMT_NB_NF: |
364 | break; |
365 | case SND_SOC_DAIFMT_NB_IF: |
366 | format = MAX98396_PCM_MODE_CFG_LRCLKEDGE; |
367 | break; |
368 | case SND_SOC_DAIFMT_IB_NF: |
369 | bclk_pol = MAX98396_PCM_MODE_CFG_BCLKEDGE; |
370 | break; |
371 | case SND_SOC_DAIFMT_IB_IF: |
372 | bclk_pol = MAX98396_PCM_MODE_CFG_BCLKEDGE; |
373 | format = MAX98396_PCM_MODE_CFG_LRCLKEDGE; |
374 | break; |
375 | |
376 | default: |
377 | dev_err(component->dev, "DAI invert mode %d unsupported\n" , |
378 | fmt & SND_SOC_DAIFMT_INV_MASK); |
379 | return -EINVAL; |
380 | } |
381 | |
382 | /* interface format */ |
383 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { |
384 | case SND_SOC_DAIFMT_I2S: |
385 | format |= MAX98396_PCM_FORMAT_I2S; |
386 | break; |
387 | case SND_SOC_DAIFMT_LEFT_J: |
388 | format |= MAX98396_PCM_FORMAT_LJ; |
389 | break; |
390 | case SND_SOC_DAIFMT_DSP_A: |
391 | format |= MAX98396_PCM_FORMAT_TDM_MODE1; |
392 | break; |
393 | case SND_SOC_DAIFMT_DSP_B: |
394 | format |= MAX98396_PCM_FORMAT_TDM_MODE0; |
395 | break; |
396 | default: |
397 | dev_err(component->dev, "DAI format %d unsupported\n" , |
398 | fmt & SND_SOC_DAIFMT_FORMAT_MASK); |
399 | return -EINVAL; |
400 | } |
401 | |
402 | ret = regmap_read(map: max98396->regmap, MAX98396_R210F_GLOBAL_EN, val: &status); |
403 | if (ret < 0) |
404 | return -EINVAL; |
405 | |
406 | if (status) { |
407 | ret = regmap_read(map: max98396->regmap, MAX98396_R2041_PCM_MODE_CFG, val: ®); |
408 | if (ret < 0) |
409 | return -EINVAL; |
410 | if (format != (reg & format_mask)) { |
411 | update = true; |
412 | } else { |
413 | ret = regmap_read(map: max98396->regmap, |
414 | MAX98396_R2042_PCM_CLK_SETUP, val: ®); |
415 | if (ret < 0) |
416 | return -EINVAL; |
417 | if (bclk_pol != (reg & MAX98396_PCM_MODE_CFG_BCLKEDGE)) |
418 | update = true; |
419 | } |
420 | /* GLOBAL_EN OFF prior to pcm mode, clock configuration change */ |
421 | if (update) |
422 | max98396_global_enable_onoff(regmap: max98396->regmap, onoff: false); |
423 | } |
424 | |
425 | regmap_update_bits(map: max98396->regmap, |
426 | MAX98396_R2041_PCM_MODE_CFG, |
427 | mask: format_mask, val: format); |
428 | |
429 | regmap_update_bits(map: max98396->regmap, |
430 | MAX98396_R2042_PCM_CLK_SETUP, |
431 | MAX98396_PCM_MODE_CFG_BCLKEDGE, |
432 | val: bclk_pol); |
433 | |
434 | if (status && update) |
435 | max98396_global_enable_onoff(regmap: max98396->regmap, onoff: true); |
436 | |
437 | return 0; |
438 | } |
439 | |
440 | #define MAX98396_BSEL_32 0x2 |
441 | #define MAX98396_BSEL_48 0x3 |
442 | #define MAX98396_BSEL_64 0x4 |
443 | #define MAX98396_BSEL_96 0x5 |
444 | #define MAX98396_BSEL_128 0x6 |
445 | #define MAX98396_BSEL_192 0x7 |
446 | #define MAX98396_BSEL_256 0x8 |
447 | #define MAX98396_BSEL_384 0x9 |
448 | #define MAX98396_BSEL_512 0xa |
449 | #define MAX98396_BSEL_320 0xb |
450 | #define MAX98396_BSEL_250 0xc |
451 | #define MAX98396_BSEL_125 0xd |
452 | |
453 | /* Refer to table 5 in the datasheet */ |
454 | static const struct max98396_pcm_config { |
455 | int in, out, width, bsel, max_sr; |
456 | } max98396_pcm_configs[] = { |
457 | { .in = 2, .out = 4, .width = 16, .bsel = MAX98396_BSEL_32, .max_sr = 192000 }, |
458 | { .in = 2, .out = 6, .width = 24, .bsel = MAX98396_BSEL_48, .max_sr = 192000 }, |
459 | { .in = 2, .out = 8, .width = 32, .bsel = MAX98396_BSEL_64, .max_sr = 192000 }, |
460 | { .in = 3, .out = 15, .width = 32, .bsel = MAX98396_BSEL_125, .max_sr = 192000 }, |
461 | { .in = 4, .out = 8, .width = 16, .bsel = MAX98396_BSEL_64, .max_sr = 192000 }, |
462 | { .in = 4, .out = 12, .width = 24, .bsel = MAX98396_BSEL_96, .max_sr = 192000 }, |
463 | { .in = 4, .out = 16, .width = 32, .bsel = MAX98396_BSEL_128, .max_sr = 192000 }, |
464 | { .in = 5, .out = 15, .width = 24, .bsel = MAX98396_BSEL_125, .max_sr = 192000 }, |
465 | { .in = 7, .out = 15, .width = 16, .bsel = MAX98396_BSEL_125, .max_sr = 192000 }, |
466 | { .in = 2, .out = 4, .width = 16, .bsel = MAX98396_BSEL_32, .max_sr = 96000 }, |
467 | { .in = 2, .out = 6, .width = 24, .bsel = MAX98396_BSEL_48, .max_sr = 96000 }, |
468 | { .in = 2, .out = 8, .width = 32, .bsel = MAX98396_BSEL_64, .max_sr = 96000 }, |
469 | { .in = 3, .out = 15, .width = 32, .bsel = MAX98396_BSEL_125, .max_sr = 96000 }, |
470 | { .in = 4, .out = 8, .width = 16, .bsel = MAX98396_BSEL_64, .max_sr = 96000 }, |
471 | { .in = 4, .out = 12, .width = 24, .bsel = MAX98396_BSEL_96, .max_sr = 96000 }, |
472 | { .in = 4, .out = 16, .width = 32, .bsel = MAX98396_BSEL_128, .max_sr = 96000 }, |
473 | { .in = 5, .out = 15, .width = 24, .bsel = MAX98396_BSEL_125, .max_sr = 96000 }, |
474 | { .in = 7, .out = 15, .width = 16, .bsel = MAX98396_BSEL_125, .max_sr = 96000 }, |
475 | { .in = 7, .out = 31, .width = 32, .bsel = MAX98396_BSEL_250, .max_sr = 96000 }, |
476 | { .in = 8, .out = 16, .width = 16, .bsel = MAX98396_BSEL_128, .max_sr = 96000 }, |
477 | { .in = 8, .out = 24, .width = 24, .bsel = MAX98396_BSEL_192, .max_sr = 96000 }, |
478 | { .in = 8, .out = 32, .width = 32, .bsel = MAX98396_BSEL_256, .max_sr = 96000 }, |
479 | { .in = 10, .out = 31, .width = 24, .bsel = MAX98396_BSEL_250, .max_sr = 96000 }, |
480 | { .in = 15, .out = 31, .width = 16, .bsel = MAX98396_BSEL_250, .max_sr = 96000 }, |
481 | { .in = 16, .out = 32, .width = 16, .bsel = MAX98396_BSEL_256, .max_sr = 96000 }, |
482 | { .in = 7, .out = 31, .width = 32, .bsel = MAX98396_BSEL_250, .max_sr = 48000 }, |
483 | { .in = 10, .out = 31, .width = 24, .bsel = MAX98396_BSEL_250, .max_sr = 48000 }, |
484 | { .in = 10, .out = 40, .width = 32, .bsel = MAX98396_BSEL_320, .max_sr = 48000 }, |
485 | { .in = 15, .out = 31, .width = 16, .bsel = MAX98396_BSEL_250, .max_sr = 48000 }, |
486 | { .in = 16, .out = 48, .width = 24, .bsel = MAX98396_BSEL_384, .max_sr = 48000 }, |
487 | { .in = 16, .out = 64, .width = 32, .bsel = MAX98396_BSEL_512, .max_sr = 48000 }, |
488 | }; |
489 | |
490 | static int max98396_pcm_config_index(int in_slots, int out_slots, int width) |
491 | { |
492 | int i; |
493 | |
494 | for (i = 0; i < ARRAY_SIZE(max98396_pcm_configs); i++) { |
495 | const struct max98396_pcm_config *c = &max98396_pcm_configs[i]; |
496 | |
497 | if (in_slots == c->in && out_slots <= c->out && width == c->width) |
498 | return i; |
499 | } |
500 | |
501 | return -1; |
502 | } |
503 | |
504 | static int max98396_dai_hw_params(struct snd_pcm_substream *substream, |
505 | struct snd_pcm_hw_params *params, |
506 | struct snd_soc_dai *dai) |
507 | { |
508 | struct snd_soc_component *component = dai->component; |
509 | struct max98396_priv *max98396 = snd_soc_component_get_drvdata(c: component); |
510 | unsigned int sampling_rate = 0; |
511 | unsigned int chan_sz = 0; |
512 | int ret, reg, status, bsel = 0; |
513 | bool update = false; |
514 | |
515 | /* pcm mode configuration */ |
516 | switch (snd_pcm_format_width(format: params_format(p: params))) { |
517 | case 16: |
518 | chan_sz = MAX98396_PCM_MODE_CFG_CHANSZ_16; |
519 | break; |
520 | case 24: |
521 | chan_sz = MAX98396_PCM_MODE_CFG_CHANSZ_24; |
522 | break; |
523 | case 32: |
524 | chan_sz = MAX98396_PCM_MODE_CFG_CHANSZ_32; |
525 | break; |
526 | default: |
527 | dev_err(component->dev, "format unsupported %d\n" , |
528 | params_format(params)); |
529 | goto err; |
530 | } |
531 | |
532 | dev_dbg(component->dev, "format supported %d" , |
533 | params_format(params)); |
534 | |
535 | /* sampling rate configuration */ |
536 | switch (params_rate(p: params)) { |
537 | case 8000: |
538 | sampling_rate = MAX98396_PCM_SR_8000; |
539 | break; |
540 | case 11025: |
541 | sampling_rate = MAX98396_PCM_SR_11025; |
542 | break; |
543 | case 12000: |
544 | sampling_rate = MAX98396_PCM_SR_12000; |
545 | break; |
546 | case 16000: |
547 | sampling_rate = MAX98396_PCM_SR_16000; |
548 | break; |
549 | case 22050: |
550 | sampling_rate = MAX98396_PCM_SR_22050; |
551 | break; |
552 | case 24000: |
553 | sampling_rate = MAX98396_PCM_SR_24000; |
554 | break; |
555 | case 32000: |
556 | sampling_rate = MAX98396_PCM_SR_32000; |
557 | break; |
558 | case 44100: |
559 | sampling_rate = MAX98396_PCM_SR_44100; |
560 | break; |
561 | case 48000: |
562 | sampling_rate = MAX98396_PCM_SR_48000; |
563 | break; |
564 | case 88200: |
565 | sampling_rate = MAX98396_PCM_SR_88200; |
566 | break; |
567 | case 96000: |
568 | sampling_rate = MAX98396_PCM_SR_96000; |
569 | break; |
570 | case 192000: |
571 | sampling_rate = MAX98396_PCM_SR_192000; |
572 | break; |
573 | default: |
574 | dev_err(component->dev, "rate %d not supported\n" , |
575 | params_rate(params)); |
576 | goto err; |
577 | } |
578 | |
579 | if (max98396->tdm_mode) { |
580 | if (params_rate(p: params) > max98396->tdm_max_samplerate) { |
581 | dev_err(component->dev, "TDM sample rate %d too high" , |
582 | params_rate(params)); |
583 | goto err; |
584 | } |
585 | } else { |
586 | /* BCLK configuration */ |
587 | ret = max98396_pcm_config_index(in_slots: params_channels(p: params), |
588 | out_slots: params_channels(p: params), |
589 | width: snd_pcm_format_width(format: params_format(p: params))); |
590 | if (ret < 0) { |
591 | dev_err(component->dev, |
592 | "no PCM config for %d channels, format %d\n" , |
593 | params_channels(params), params_format(params)); |
594 | goto err; |
595 | } |
596 | |
597 | bsel = max98396_pcm_configs[ret].bsel; |
598 | |
599 | if (params_rate(p: params) > max98396_pcm_configs[ret].max_sr) { |
600 | dev_err(component->dev, "sample rate %d too high" , |
601 | params_rate(params)); |
602 | goto err; |
603 | } |
604 | } |
605 | |
606 | ret = regmap_read(map: max98396->regmap, MAX98396_R210F_GLOBAL_EN, val: &status); |
607 | if (ret < 0) |
608 | goto err; |
609 | |
610 | if (status) { |
611 | ret = regmap_read(map: max98396->regmap, MAX98396_R2041_PCM_MODE_CFG, val: ®); |
612 | if (ret < 0) |
613 | goto err; |
614 | if (chan_sz != (reg & MAX98396_PCM_MODE_CFG_CHANSZ_MASK)) { |
615 | update = true; |
616 | } else { |
617 | ret = regmap_read(map: max98396->regmap, MAX98396_R2043_PCM_SR_SETUP, val: ®); |
618 | if (ret < 0) |
619 | goto err; |
620 | if (sampling_rate != (reg & MAX98396_PCM_SR_MASK)) |
621 | update = true; |
622 | } |
623 | |
624 | /* GLOBAL_EN OFF prior to channel size and sampling rate change */ |
625 | if (update) |
626 | max98396_global_enable_onoff(regmap: max98396->regmap, onoff: false); |
627 | } |
628 | |
629 | /* set channel size */ |
630 | regmap_update_bits(map: max98396->regmap, MAX98396_R2041_PCM_MODE_CFG, |
631 | MAX98396_PCM_MODE_CFG_CHANSZ_MASK, val: chan_sz); |
632 | |
633 | /* set DAI_SR to correct LRCLK frequency */ |
634 | regmap_update_bits(map: max98396->regmap, MAX98396_R2043_PCM_SR_SETUP, |
635 | MAX98396_PCM_SR_MASK, val: sampling_rate); |
636 | |
637 | /* set sampling rate of IV */ |
638 | if (max98396->interleave_mode && |
639 | sampling_rate > MAX98396_PCM_SR_16000) |
640 | regmap_update_bits(map: max98396->regmap, |
641 | MAX98396_R2043_PCM_SR_SETUP, |
642 | MAX98396_IVADC_SR_MASK, |
643 | val: (sampling_rate - 3) |
644 | << MAX98396_IVADC_SR_SHIFT); |
645 | else |
646 | regmap_update_bits(map: max98396->regmap, |
647 | MAX98396_R2043_PCM_SR_SETUP, |
648 | MAX98396_IVADC_SR_MASK, |
649 | val: sampling_rate << MAX98396_IVADC_SR_SHIFT); |
650 | |
651 | if (bsel) |
652 | regmap_update_bits(map: max98396->regmap, |
653 | MAX98396_R2042_PCM_CLK_SETUP, |
654 | MAX98396_PCM_CLK_SETUP_BSEL_MASK, |
655 | val: bsel); |
656 | |
657 | if (status && update) |
658 | max98396_global_enable_onoff(regmap: max98396->regmap, onoff: true); |
659 | |
660 | return 0; |
661 | |
662 | err: |
663 | return -EINVAL; |
664 | } |
665 | |
666 | static int max98396_dai_tdm_slot(struct snd_soc_dai *dai, |
667 | unsigned int tx_mask, unsigned int rx_mask, |
668 | int slots, int slot_width) |
669 | { |
670 | struct snd_soc_component *component = dai->component; |
671 | struct max98396_priv *max98396 = |
672 | snd_soc_component_get_drvdata(c: component); |
673 | int bsel; |
674 | unsigned int chan_sz = 0; |
675 | int ret, status; |
676 | int reg; |
677 | bool update = false; |
678 | |
679 | if (!tx_mask && !rx_mask && !slots && !slot_width) |
680 | max98396->tdm_mode = false; |
681 | else |
682 | max98396->tdm_mode = true; |
683 | |
684 | /* BCLK configuration */ |
685 | ret = max98396_pcm_config_index(in_slots: slots, out_slots: slots, width: slot_width); |
686 | if (ret < 0) { |
687 | dev_err(component->dev, "no TDM config for %d slots %d bits\n" , |
688 | slots, slot_width); |
689 | return -EINVAL; |
690 | } |
691 | |
692 | bsel = max98396_pcm_configs[ret].bsel; |
693 | max98396->tdm_max_samplerate = max98396_pcm_configs[ret].max_sr; |
694 | |
695 | /* Channel size configuration */ |
696 | switch (slot_width) { |
697 | case 16: |
698 | chan_sz = MAX98396_PCM_MODE_CFG_CHANSZ_16; |
699 | break; |
700 | case 24: |
701 | chan_sz = MAX98396_PCM_MODE_CFG_CHANSZ_24; |
702 | break; |
703 | case 32: |
704 | chan_sz = MAX98396_PCM_MODE_CFG_CHANSZ_32; |
705 | break; |
706 | default: |
707 | dev_err(component->dev, "slot width %d unsupported\n" , |
708 | slot_width); |
709 | return -EINVAL; |
710 | } |
711 | |
712 | ret = regmap_read(map: max98396->regmap, MAX98396_R210F_GLOBAL_EN, val: &status); |
713 | if (ret < 0) |
714 | return -EINVAL; |
715 | |
716 | if (status) { |
717 | ret = regmap_read(map: max98396->regmap, MAX98396_R2042_PCM_CLK_SETUP, val: ®); |
718 | if (ret < 0) |
719 | return -EINVAL; |
720 | if (bsel != (reg & MAX98396_PCM_CLK_SETUP_BSEL_MASK)) { |
721 | update = true; |
722 | } else { |
723 | ret = regmap_read(map: max98396->regmap, MAX98396_R2041_PCM_MODE_CFG, val: ®); |
724 | if (ret < 0) |
725 | return -EINVAL; |
726 | if (chan_sz != (reg & MAX98396_PCM_MODE_CFG_CHANSZ_MASK)) |
727 | update = true; |
728 | } |
729 | |
730 | /* GLOBAL_EN OFF prior to channel size and BCLK per LRCLK change */ |
731 | if (update) |
732 | max98396_global_enable_onoff(regmap: max98396->regmap, onoff: false); |
733 | } |
734 | |
735 | regmap_update_bits(map: max98396->regmap, |
736 | MAX98396_R2042_PCM_CLK_SETUP, |
737 | MAX98396_PCM_CLK_SETUP_BSEL_MASK, |
738 | val: bsel); |
739 | |
740 | regmap_update_bits(map: max98396->regmap, |
741 | MAX98396_R2041_PCM_MODE_CFG, |
742 | MAX98396_PCM_MODE_CFG_CHANSZ_MASK, val: chan_sz); |
743 | |
744 | /* Rx slot configuration */ |
745 | if (max98396->device_id == CODEC_TYPE_MAX98396) { |
746 | regmap_update_bits(map: max98396->regmap, |
747 | MAX98396_R2056_PCM_RX_SRC2, |
748 | MAX98396_PCM_DMIX_CH0_SRC_MASK, |
749 | val: rx_mask); |
750 | regmap_update_bits(map: max98396->regmap, |
751 | MAX98396_R2056_PCM_RX_SRC2, |
752 | MAX98396_PCM_DMIX_CH1_SRC_MASK, |
753 | val: rx_mask << MAX98396_PCM_DMIX_CH1_SHIFT); |
754 | } else { |
755 | regmap_update_bits(map: max98396->regmap, |
756 | MAX98397_R2057_PCM_RX_SRC2, |
757 | MAX98396_PCM_DMIX_CH0_SRC_MASK, |
758 | val: rx_mask); |
759 | regmap_update_bits(map: max98396->regmap, |
760 | MAX98397_R2057_PCM_RX_SRC2, |
761 | MAX98396_PCM_DMIX_CH1_SRC_MASK, |
762 | val: rx_mask << MAX98396_PCM_DMIX_CH1_SHIFT); |
763 | } |
764 | |
765 | /* Tx slot Hi-Z configuration */ |
766 | if (max98396->device_id == CODEC_TYPE_MAX98396) { |
767 | regmap_write(map: max98396->regmap, |
768 | MAX98396_R2053_PCM_TX_HIZ_CTRL_8, |
769 | val: ~tx_mask & 0xFF); |
770 | regmap_write(map: max98396->regmap, |
771 | MAX98396_R2052_PCM_TX_HIZ_CTRL_7, |
772 | val: (~tx_mask & 0xFF00) >> 8); |
773 | } else { |
774 | regmap_write(map: max98396->regmap, |
775 | MAX98397_R2054_PCM_TX_HIZ_CTRL_8, |
776 | val: ~tx_mask & 0xFF); |
777 | regmap_write(map: max98396->regmap, |
778 | MAX98397_R2053_PCM_TX_HIZ_CTRL_7, |
779 | val: (~tx_mask & 0xFF00) >> 8); |
780 | } |
781 | |
782 | if (status && update) |
783 | max98396_global_enable_onoff(regmap: max98396->regmap, onoff: true); |
784 | |
785 | return 0; |
786 | } |
787 | |
788 | #define MAX98396_RATES SNDRV_PCM_RATE_8000_192000 |
789 | |
790 | #define MAX98396_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \ |
791 | SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE) |
792 | |
793 | static const struct snd_soc_dai_ops max98396_dai_ops = { |
794 | .set_fmt = max98396_dai_set_fmt, |
795 | .hw_params = max98396_dai_hw_params, |
796 | .set_tdm_slot = max98396_dai_tdm_slot, |
797 | }; |
798 | |
799 | static int max98396_dac_event(struct snd_soc_dapm_widget *w, |
800 | struct snd_kcontrol *kcontrol, int event) |
801 | { |
802 | struct snd_soc_component *component = |
803 | snd_soc_dapm_to_component(dapm: w->dapm); |
804 | struct max98396_priv *max98396 = |
805 | snd_soc_component_get_drvdata(c: component); |
806 | |
807 | switch (event) { |
808 | case SND_SOC_DAPM_POST_PMU: |
809 | max98396_global_enable_onoff(regmap: max98396->regmap, onoff: true); |
810 | break; |
811 | case SND_SOC_DAPM_PRE_PMD: |
812 | max98396_global_enable_onoff(regmap: max98396->regmap, onoff: false); |
813 | |
814 | max98396->tdm_mode = false; |
815 | break; |
816 | default: |
817 | return 0; |
818 | } |
819 | return 0; |
820 | } |
821 | |
822 | static bool max98396_readable_register(struct device *dev, unsigned int reg) |
823 | { |
824 | switch (reg) { |
825 | case MAX98396_R2001_INT_RAW1 ... MAX98396_R2004_INT_RAW4: |
826 | case MAX98396_R2006_INT_STATE1 ... MAX98396_R2009_INT_STATE4: |
827 | case MAX98396_R200B_INT_FLAG1 ... MAX98396_R200E_INT_FLAG4: |
828 | case MAX98396_R2010_INT_EN1 ... MAX98396_R2013_INT_EN4: |
829 | case MAX98396_R2015_INT_FLAG_CLR1 ... MAX98396_R2018_INT_FLAG_CLR4: |
830 | case MAX98396_R201F_IRQ_CTRL ... MAX98396_R2024_THERM_FOLDBACK_SET: |
831 | case MAX98396_R2027_THERM_FOLDBACK_EN: |
832 | case MAX98396_R2030_NOISEGATE_MODE_CTRL: |
833 | case MAX98396_R2033_NOISEGATE_MODE_EN: |
834 | case MAX98396_R2038_CLK_MON_CTRL ... MAX98396_R2039_DATA_MON_CTRL: |
835 | case MAX98396_R203F_ENABLE_CTRLS ... MAX98396_R2053_PCM_TX_HIZ_CTRL_8: |
836 | case MAX98396_R2055_PCM_RX_SRC1 ... MAX98396_R2056_PCM_RX_SRC2: |
837 | case MAX98396_R2058_PCM_BYPASS_SRC: |
838 | case MAX98396_R205D_PCM_TX_SRC_EN ... MAX98396_R205F_PCM_TX_EN: |
839 | case MAX98396_R2070_ICC_RX_EN_A... MAX98396_R2072_ICC_TX_CTRL: |
840 | case MAX98396_R207F_ICC_EN: |
841 | case MAX98396_R2083_TONE_GEN_DC_CFG ... MAX98396_R2086_TONE_GEN_DC_LVL3: |
842 | case MAX98396_R208F_TONE_GEN_EN ... MAX98396_R209A_SPK_EDGE_CTRL: |
843 | case MAX98396_R209C_SPK_EDGE_CTRL1 ... MAX98396_R20A0_AMP_SUPPLY_CTL: |
844 | case MAX98396_R20AF_AMP_EN ... MAX98396_R20BF_ADC_LO_VBAT_READBACK_LSB: |
845 | case MAX98396_R20C7_ADC_CFG: |
846 | case MAX98396_R20D0_DHT_CFG1 ... MAX98396_R20D6_DHT_HYSTERESIS_CFG: |
847 | case MAX98396_R20DF_DHT_EN: |
848 | case MAX98396_R20E0_IV_SENSE_PATH_CFG: |
849 | case MAX98396_R20E4_IV_SENSE_PATH_EN |
850 | ... MAX98396_R2106_BPE_THRESH_HYSTERESIS: |
851 | case MAX98396_R2108_BPE_SUPPLY_SRC ... MAX98396_R210B_BPE_LOW_LIMITER: |
852 | case MAX98396_R210D_BPE_EN ... MAX98396_R210F_GLOBAL_EN: |
853 | case MAX98396_R21FF_REVISION_ID: |
854 | return true; |
855 | default: |
856 | return false; |
857 | } |
858 | }; |
859 | |
860 | static bool max98396_volatile_reg(struct device *dev, unsigned int reg) |
861 | { |
862 | switch (reg) { |
863 | case MAX98396_R2000_SW_RESET: |
864 | case MAX98396_R2001_INT_RAW1 ... MAX98396_R200E_INT_FLAG4: |
865 | case MAX98396_R2041_PCM_MODE_CFG: |
866 | case MAX98396_R20B6_ADC_PVDD_READBACK_MSB |
867 | ... MAX98396_R20BF_ADC_LO_VBAT_READBACK_LSB: |
868 | case MAX98396_R20E5_BPE_STATE: |
869 | case MAX98396_R2109_BPE_LOW_STATE |
870 | ... MAX98396_R210B_BPE_LOW_LIMITER: |
871 | case MAX98396_R210F_GLOBAL_EN: |
872 | case MAX98396_R21FF_REVISION_ID: |
873 | return true; |
874 | default: |
875 | return false; |
876 | } |
877 | } |
878 | |
879 | static bool max98397_readable_register(struct device *dev, unsigned int reg) |
880 | { |
881 | switch (reg) { |
882 | case MAX98396_R2001_INT_RAW1 ... MAX98396_R2004_INT_RAW4: |
883 | case MAX98396_R2006_INT_STATE1 ... MAX98396_R2009_INT_STATE4: |
884 | case MAX98396_R200B_INT_FLAG1 ... MAX98396_R200E_INT_FLAG4: |
885 | case MAX98396_R2010_INT_EN1 ... MAX98396_R2013_INT_EN4: |
886 | case MAX98396_R2015_INT_FLAG_CLR1 ... MAX98396_R2018_INT_FLAG_CLR4: |
887 | case MAX98396_R201F_IRQ_CTRL ... MAX98396_R2024_THERM_FOLDBACK_SET: |
888 | case MAX98396_R2027_THERM_FOLDBACK_EN: |
889 | case MAX98396_R2030_NOISEGATE_MODE_CTRL: |
890 | case MAX98396_R2033_NOISEGATE_MODE_EN: |
891 | case MAX98396_R2038_CLK_MON_CTRL ... MAX98397_R203A_SPK_MON_THRESH: |
892 | case MAX98396_R203F_ENABLE_CTRLS ... MAX98397_R2054_PCM_TX_HIZ_CTRL_8: |
893 | case MAX98397_R2056_PCM_RX_SRC1... MAX98396_R2058_PCM_BYPASS_SRC: |
894 | case MAX98396_R205D_PCM_TX_SRC_EN ... MAX98397_R2060_PCM_TX_SUPPLY_SEL: |
895 | case MAX98396_R2070_ICC_RX_EN_A... MAX98396_R2072_ICC_TX_CTRL: |
896 | case MAX98396_R207F_ICC_EN: |
897 | case MAX98396_R2083_TONE_GEN_DC_CFG ... MAX98396_R2086_TONE_GEN_DC_LVL3: |
898 | case MAX98396_R208F_TONE_GEN_EN ... MAX98396_R209F_BYPASS_PATH_CFG: |
899 | case MAX98396_R20AF_AMP_EN ... MAX98397_R20C5_MEAS_ADC_OPTIMAL_MODE: |
900 | case MAX98396_R20C7_ADC_CFG: |
901 | case MAX98396_R20D0_DHT_CFG1 ... MAX98396_R20D6_DHT_HYSTERESIS_CFG: |
902 | case MAX98396_R20DF_DHT_EN: |
903 | case MAX98396_R20E0_IV_SENSE_PATH_CFG: |
904 | case MAX98396_R20E4_IV_SENSE_PATH_EN |
905 | ... MAX98396_R2106_BPE_THRESH_HYSTERESIS: |
906 | case MAX98396_R2108_BPE_SUPPLY_SRC ... MAX98396_R210B_BPE_LOW_LIMITER: |
907 | case MAX98396_R210D_BPE_EN ... MAX98396_R210F_GLOBAL_EN: |
908 | case MAX98397_R22FF_REVISION_ID: |
909 | return true; |
910 | default: |
911 | return false; |
912 | } |
913 | }; |
914 | |
915 | static bool max98397_volatile_reg(struct device *dev, unsigned int reg) |
916 | { |
917 | switch (reg) { |
918 | case MAX98396_R2001_INT_RAW1 ... MAX98396_R200E_INT_FLAG4: |
919 | case MAX98396_R2041_PCM_MODE_CFG: |
920 | case MAX98397_R20B7_ADC_PVDD_READBACK_MSB |
921 | ... MAX98397_R20C4_ADC_LO_VDDH_READBACK_LSB: |
922 | case MAX98396_R20E5_BPE_STATE: |
923 | case MAX98396_R2109_BPE_LOW_STATE |
924 | ... MAX98396_R210B_BPE_LOW_LIMITER: |
925 | case MAX98396_R210F_GLOBAL_EN: |
926 | case MAX98397_R22FF_REVISION_ID: |
927 | return true; |
928 | default: |
929 | return false; |
930 | } |
931 | } |
932 | |
933 | static const char * const max98396_op_mod_text[] = { |
934 | "DG" , "PVDD" , "VBAT" , |
935 | }; |
936 | |
937 | static SOC_ENUM_SINGLE_DECL(max98396_op_mod_enum, |
938 | MAX98396_R2098_SPK_CLS_DG_MODE, |
939 | 0, max98396_op_mod_text); |
940 | |
941 | static DECLARE_TLV_DB_SCALE(max98396_digital_tlv, -6350, 50, 1); |
942 | static const DECLARE_TLV_DB_RANGE(max98396_spk_tlv, |
943 | 0, 0x11, TLV_DB_SCALE_ITEM(400, 100, 0), |
944 | ); |
945 | static DECLARE_TLV_DB_RANGE(max98397_digital_tlv, |
946 | 0, 0x4A, TLV_DB_SCALE_ITEM(TLV_DB_GAIN_MUTE, 0, 1), |
947 | 0x4B, 0xFF, TLV_DB_SCALE_ITEM(-9000, 50, 0), |
948 | ); |
949 | static const DECLARE_TLV_DB_RANGE(max98397_spk_tlv, |
950 | 0, 0x15, TLV_DB_SCALE_ITEM(600, 100, 0), |
951 | ); |
952 | |
953 | static int max98396_mux_get(struct snd_kcontrol *kcontrol, |
954 | struct snd_ctl_elem_value *ucontrol) |
955 | { |
956 | struct snd_soc_component *component = |
957 | snd_soc_dapm_kcontrol_component(kcontrol); |
958 | struct max98396_priv *max98396 = snd_soc_component_get_drvdata(c: component); |
959 | int reg, val; |
960 | |
961 | if (max98396->device_id == CODEC_TYPE_MAX98396) |
962 | reg = MAX98396_R2055_PCM_RX_SRC1; |
963 | else |
964 | reg = MAX98397_R2056_PCM_RX_SRC1; |
965 | |
966 | regmap_read(map: max98396->regmap, reg, val: &val); |
967 | |
968 | ucontrol->value.enumerated.item[0] = val; |
969 | |
970 | return 0; |
971 | } |
972 | |
973 | static int max98396_mux_put(struct snd_kcontrol *kcontrol, |
974 | struct snd_ctl_elem_value *ucontrol) |
975 | { |
976 | struct snd_soc_component *component = |
977 | snd_soc_dapm_kcontrol_component(kcontrol); |
978 | struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_dapm(kcontrol); |
979 | struct max98396_priv *max98396 = snd_soc_component_get_drvdata(c: component); |
980 | struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; |
981 | unsigned int *item = ucontrol->value.enumerated.item; |
982 | int reg, val; |
983 | int change; |
984 | |
985 | if (item[0] >= e->items) |
986 | return -EINVAL; |
987 | |
988 | val = snd_soc_enum_item_to_val(e, item: item[0]) << e->shift_l; |
989 | |
990 | if (max98396->device_id == CODEC_TYPE_MAX98396) |
991 | reg = MAX98396_R2055_PCM_RX_SRC1; |
992 | else |
993 | reg = MAX98397_R2056_PCM_RX_SRC1; |
994 | |
995 | change = snd_soc_component_test_bits(component, reg, |
996 | MAX98396_PCM_RX_MASK, value: val); |
997 | |
998 | if (change) |
999 | regmap_update_bits(map: max98396->regmap, reg, |
1000 | MAX98396_PCM_RX_MASK, val); |
1001 | |
1002 | snd_soc_dapm_mux_update_power(dapm, kcontrol, mux: item[0], e, NULL); |
1003 | |
1004 | return change; |
1005 | } |
1006 | |
1007 | static const char * const max98396_switch_text[] = { |
1008 | "Left" , "Right" , "LeftRight" }; |
1009 | |
1010 | static SOC_ENUM_SINGLE_DECL(dai_sel_enum, SND_SOC_NOPM, 0, |
1011 | max98396_switch_text); |
1012 | |
1013 | static const struct snd_kcontrol_new max98396_dai_mux = |
1014 | SOC_DAPM_ENUM_EXT("DAI Sel Mux" , dai_sel_enum, |
1015 | max98396_mux_get, max98396_mux_put); |
1016 | |
1017 | static const struct snd_kcontrol_new max98396_vi_control = |
1018 | SOC_DAPM_SINGLE("Switch" , MAX98396_R205F_PCM_TX_EN, 0, 1, 0); |
1019 | |
1020 | static const struct snd_soc_dapm_widget max98396_dapm_widgets[] = { |
1021 | SND_SOC_DAPM_DAC_E("Amp Enable" , "HiFi Playback" , |
1022 | MAX98396_R20AF_AMP_EN, 0, 0, max98396_dac_event, |
1023 | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), |
1024 | SND_SOC_DAPM_MUX("DAI Sel Mux" , SND_SOC_NOPM, 0, 0, |
1025 | &max98396_dai_mux), |
1026 | SND_SOC_DAPM_OUTPUT("BE_OUT" ), |
1027 | SND_SOC_DAPM_AIF_OUT("Voltage Sense" , "HiFi Capture" , 0, |
1028 | MAX98396_R20E4_IV_SENSE_PATH_EN, 0, 0), |
1029 | SND_SOC_DAPM_AIF_OUT("Current Sense" , "HiFi Capture" , 0, |
1030 | MAX98396_R20E4_IV_SENSE_PATH_EN, 1, 0), |
1031 | SND_SOC_DAPM_SWITCH("VI Sense" , SND_SOC_NOPM, 0, 0, |
1032 | &max98396_vi_control), |
1033 | SND_SOC_DAPM_SIGGEN("VMON" ), |
1034 | SND_SOC_DAPM_SIGGEN("IMON" ), |
1035 | SND_SOC_DAPM_SIGGEN("FBMON" ), |
1036 | }; |
1037 | |
1038 | static const char * const max98396_thermal_thresh_text[] = { |
1039 | "50C" , "51C" , "52C" , "53C" , "54C" , "55C" , "56C" , "57C" , |
1040 | "58C" , "59C" , "60C" , "61C" , "62C" , "63C" , "64C" , "65C" , |
1041 | "66C" , "67C" , "68C" , "69C" , "70C" , "71C" , "72C" , "73C" , |
1042 | "74C" , "75C" , "76C" , "77C" , "78C" , "79C" , "80C" , "81C" , |
1043 | "82C" , "83C" , "84C" , "85C" , "86C" , "87C" , "88C" , "89C" , |
1044 | "90C" , "91C" , "92C" , "93C" , "94C" , "95C" , "96C" , "97C" , |
1045 | "98C" , "99C" , "100C" , "101C" , "102C" , "103C" , "104C" , "105C" , |
1046 | "106C" , "107C" , "108C" , "109C" , "110C" , "111C" , "112C" , "113C" , |
1047 | "114C" , "115C" , "116C" , "117C" , "118C" , "119C" , "120C" , "121C" , |
1048 | "122C" , "123C" , "124C" , "125C" , "126C" , "127C" , "128C" , "129C" , |
1049 | "130C" , "131C" , "132C" , "133C" , "134C" , "135C" , "136C" , "137C" , |
1050 | "138C" , "139C" , "140C" , "141C" , "142C" , "143C" , "144C" , "145C" , |
1051 | "146C" , "147C" , "148C" , "149C" , "150C" |
1052 | }; |
1053 | |
1054 | static SOC_ENUM_SINGLE_DECL(max98396_thermal_warn_thresh1_enum, |
1055 | MAX98396_R2020_THERM_WARN_THRESH, 0, |
1056 | max98396_thermal_thresh_text); |
1057 | |
1058 | static SOC_ENUM_SINGLE_DECL(max98396_thermal_warn_thresh2_enum, |
1059 | MAX98396_R2021_THERM_WARN_THRESH2, 0, |
1060 | max98396_thermal_thresh_text); |
1061 | |
1062 | static SOC_ENUM_SINGLE_DECL(max98396_thermal_shdn_thresh_enum, |
1063 | MAX98396_R2022_THERM_SHDN_THRESH, 0, |
1064 | max98396_thermal_thresh_text); |
1065 | |
1066 | static const char * const max98396_thermal_hyteresis_text[] = { |
1067 | "2C" , "5C" , "7C" , "10C" |
1068 | }; |
1069 | |
1070 | static SOC_ENUM_SINGLE_DECL(max98396_thermal_hysteresis_enum, |
1071 | MAX98396_R2023_THERM_HYSTERESIS, 0, |
1072 | max98396_thermal_hyteresis_text); |
1073 | |
1074 | static const char * const max98396_foldback_slope_text[] = { |
1075 | "0.25" , "0.5" , "1.0" , "2.0" |
1076 | }; |
1077 | |
1078 | static SOC_ENUM_SINGLE_DECL(max98396_thermal_fb_slope1_enum, |
1079 | MAX98396_R2024_THERM_FOLDBACK_SET, |
1080 | MAX98396_THERM_FB_SLOPE1_SHIFT, |
1081 | max98396_foldback_slope_text); |
1082 | |
1083 | static SOC_ENUM_SINGLE_DECL(max98396_thermal_fb_slope2_enum, |
1084 | MAX98396_R2024_THERM_FOLDBACK_SET, |
1085 | MAX98396_THERM_FB_SLOPE2_SHIFT, |
1086 | max98396_foldback_slope_text); |
1087 | |
1088 | static const char * const max98396_foldback_reltime_text[] = { |
1089 | "3ms" , "10ms" , "100ms" , "300ms" |
1090 | }; |
1091 | |
1092 | static SOC_ENUM_SINGLE_DECL(max98396_thermal_fb_reltime_enum, |
1093 | MAX98396_R2024_THERM_FOLDBACK_SET, |
1094 | MAX98396_THERM_FB_REL_SHIFT, |
1095 | max98396_foldback_reltime_text); |
1096 | |
1097 | static const char * const max98396_foldback_holdtime_text[] = { |
1098 | "0ms" , "20ms" , "40ms" , "80ms" |
1099 | }; |
1100 | |
1101 | static SOC_ENUM_SINGLE_DECL(max98396_thermal_fb_holdtime_enum, |
1102 | MAX98396_R2024_THERM_FOLDBACK_SET, |
1103 | MAX98396_THERM_FB_HOLD_SHIFT, |
1104 | max98396_foldback_holdtime_text); |
1105 | |
1106 | static int max98396_adc_value_get(struct snd_kcontrol *kcontrol, |
1107 | struct snd_ctl_elem_value *ucontrol) |
1108 | { |
1109 | struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); |
1110 | struct soc_mixer_control *mc = |
1111 | (struct soc_mixer_control *)kcontrol->private_value; |
1112 | struct max98396_priv *max98396 = snd_soc_component_get_drvdata(c: component); |
1113 | int ret; |
1114 | u8 val[2]; |
1115 | int reg = mc->reg; |
1116 | |
1117 | /* ADC value is not available if the device is powered down */ |
1118 | if (snd_soc_component_get_bias_level(component) == SND_SOC_BIAS_OFF) |
1119 | goto exit; |
1120 | |
1121 | if (max98396->device_id == CODEC_TYPE_MAX98397) { |
1122 | switch (mc->reg) { |
1123 | case MAX98396_R20B6_ADC_PVDD_READBACK_MSB: |
1124 | reg = MAX98397_R20B7_ADC_PVDD_READBACK_MSB; |
1125 | break; |
1126 | case MAX98396_R20B8_ADC_VBAT_READBACK_MSB: |
1127 | reg = MAX98397_R20B9_ADC_VBAT_READBACK_MSB; |
1128 | break; |
1129 | case MAX98396_R20BA_ADC_TEMP_READBACK_MSB: |
1130 | reg = MAX98397_R20BB_ADC_TEMP_READBACK_MSB; |
1131 | break; |
1132 | default: |
1133 | goto exit; |
1134 | } |
1135 | } |
1136 | |
1137 | ret = regmap_raw_read(map: max98396->regmap, reg, val: &val, val_len: 2); |
1138 | if (ret) |
1139 | goto exit; |
1140 | |
1141 | /* ADC readback bits[8:0] rearrangement */ |
1142 | ucontrol->value.integer.value[0] = (val[0] << 1) | (val[1] & 1); |
1143 | return 0; |
1144 | |
1145 | exit: |
1146 | ucontrol->value.integer.value[0] = 0; |
1147 | return 0; |
1148 | } |
1149 | |
1150 | static const struct snd_kcontrol_new max98396_snd_controls[] = { |
1151 | /* Volume */ |
1152 | SOC_SINGLE_TLV("Digital Volume" , MAX98396_R2090_AMP_VOL_CTRL, |
1153 | 0, 0x7F, 1, max98396_digital_tlv), |
1154 | SOC_SINGLE_TLV("Speaker Volume" , MAX98396_R2091_AMP_PATH_GAIN, |
1155 | 0, 0x11, 0, max98396_spk_tlv), |
1156 | /* Volume Ramp Up/Down Enable*/ |
1157 | SOC_SINGLE("Ramp Up Switch" , MAX98396_R2092_AMP_DSP_CFG, |
1158 | MAX98396_DSP_SPK_VOL_RMPUP_SHIFT, 1, 0), |
1159 | SOC_SINGLE("Ramp Down Switch" , MAX98396_R2092_AMP_DSP_CFG, |
1160 | MAX98396_DSP_SPK_VOL_RMPDN_SHIFT, 1, 0), |
1161 | /* Clock Monitor Enable */ |
1162 | SOC_SINGLE("CLK Monitor Switch" , MAX98396_R203F_ENABLE_CTRLS, |
1163 | MAX98396_CTRL_CMON_EN_SHIFT, 1, 0), |
1164 | /* Dither Enable */ |
1165 | SOC_SINGLE("Dither Switch" , MAX98396_R2092_AMP_DSP_CFG, |
1166 | MAX98396_DSP_SPK_DITH_EN_SHIFT, 1, 0), |
1167 | SOC_SINGLE("IV Dither Switch" , MAX98396_R20E0_IV_SENSE_PATH_CFG, |
1168 | MAX98396_IV_SENSE_DITH_EN_SHIFT, 1, 0), |
1169 | /* DC Blocker Enable */ |
1170 | SOC_SINGLE("DC Blocker Switch" , MAX98396_R2092_AMP_DSP_CFG, |
1171 | MAX98396_DSP_SPK_DCBLK_EN_SHIFT, 1, 0), |
1172 | SOC_SINGLE("IV DC Blocker Switch" , MAX98396_R20E0_IV_SENSE_PATH_CFG, |
1173 | MAX98396_IV_SENSE_DCBLK_EN_SHIFT, 3, 0), |
1174 | /* Speaker Safe Mode Enable */ |
1175 | SOC_SINGLE("Safe Mode Switch" , MAX98396_R2092_AMP_DSP_CFG, |
1176 | MAX98396_DSP_SPK_SAFE_EN_SHIFT, 1, 0), |
1177 | /* Wideband Filter Enable */ |
1178 | SOC_SINGLE("WB Filter Switch" , MAX98396_R2092_AMP_DSP_CFG, |
1179 | MAX98396_DSP_SPK_WB_FLT_EN_SHIFT, 1, 0), |
1180 | SOC_SINGLE("IV WB Filter Switch" , MAX98396_R20E0_IV_SENSE_PATH_CFG, |
1181 | MAX98396_IV_SENSE_WB_FLT_EN_SHIFT, 1, 0), |
1182 | /* Dynamic Headroom Tracking */ |
1183 | SOC_SINGLE("DHT Switch" , MAX98396_R20DF_DHT_EN, 0, 1, 0), |
1184 | /* Brownout Protection Engine */ |
1185 | SOC_SINGLE("BPE Switch" , MAX98396_R210D_BPE_EN, 0, 1, 0), |
1186 | SOC_SINGLE("BPE Limiter Switch" , MAX98396_R210D_BPE_EN, 1, 1, 0), |
1187 | /* Bypass Path Enable */ |
1188 | SOC_SINGLE("Bypass Path Switch" , |
1189 | MAX98396_R205E_PCM_RX_EN, 1, 1, 0), |
1190 | /* Speaker Operation Mode */ |
1191 | SOC_ENUM("OP Mode" , max98396_op_mod_enum), |
1192 | /* Auto Restart functions */ |
1193 | SOC_SINGLE("CMON Auto Restart Switch" , MAX98396_R2038_CLK_MON_CTRL, |
1194 | MAX98396_CLK_MON_AUTO_RESTART_SHIFT, 1, 0), |
1195 | SOC_SINGLE("PVDD Auto Restart Switch" , MAX98396_R210E_AUTO_RESTART, |
1196 | MAX98396_PVDD_UVLO_RESTART_SHFT, 1, 0), |
1197 | SOC_SINGLE("VBAT Auto Restart Switch" , MAX98396_R210E_AUTO_RESTART, |
1198 | MAX98396_VBAT_UVLO_RESTART_SHFT, 1, 0), |
1199 | SOC_SINGLE("THERM Auto Restart Switch" , MAX98396_R210E_AUTO_RESTART, |
1200 | MAX98396_THEM_SHDN_RESTART_SHFT, 1, 0), |
1201 | SOC_SINGLE("OVC Auto Restart Switch" , MAX98396_R210E_AUTO_RESTART, |
1202 | MAX98396_OVC_RESTART_SHFT, 1, 0), |
1203 | /* Thermal Threshold */ |
1204 | SOC_ENUM("THERM Thresh1" , max98396_thermal_warn_thresh1_enum), |
1205 | SOC_ENUM("THERM Thresh2" , max98396_thermal_warn_thresh2_enum), |
1206 | SOC_ENUM("THERM SHDN Thresh" , max98396_thermal_shdn_thresh_enum), |
1207 | SOC_ENUM("THERM Hysteresis" , max98396_thermal_hysteresis_enum), |
1208 | SOC_SINGLE("THERM Foldback Switch" , |
1209 | MAX98396_R2027_THERM_FOLDBACK_EN, 0, 1, 0), |
1210 | SOC_ENUM("THERM Slope1" , max98396_thermal_fb_slope1_enum), |
1211 | SOC_ENUM("THERM Slope2" , max98396_thermal_fb_slope2_enum), |
1212 | SOC_ENUM("THERM Release" , max98396_thermal_fb_reltime_enum), |
1213 | SOC_ENUM("THERM Hold" , max98396_thermal_fb_holdtime_enum), |
1214 | /* ADC */ |
1215 | SOC_SINGLE_EXT("ADC PVDD" , MAX98396_R20B6_ADC_PVDD_READBACK_MSB, 0, 0x1FF, 0, |
1216 | max98396_adc_value_get, NULL), |
1217 | SOC_SINGLE_EXT("ADC VBAT" , MAX98396_R20B8_ADC_VBAT_READBACK_MSB, 0, 0x1FF, 0, |
1218 | max98396_adc_value_get, NULL), |
1219 | SOC_SINGLE_EXT("ADC TEMP" , MAX98396_R20BA_ADC_TEMP_READBACK_MSB, 0, 0x1FF, 0, |
1220 | max98396_adc_value_get, NULL), |
1221 | }; |
1222 | |
1223 | static const struct snd_kcontrol_new max98397_snd_controls[] = { |
1224 | /* Volume */ |
1225 | SOC_SINGLE_TLV("Digital Volume" , MAX98396_R2090_AMP_VOL_CTRL, |
1226 | 0, 0xFF, 1, max98397_digital_tlv), |
1227 | SOC_SINGLE_TLV("Speaker Volume" , MAX98396_R2091_AMP_PATH_GAIN, |
1228 | 0, 0x15, 0, max98397_spk_tlv), |
1229 | /* Volume Ramp Up/Down Enable*/ |
1230 | SOC_SINGLE("Ramp Up Switch" , MAX98396_R2092_AMP_DSP_CFG, |
1231 | MAX98396_DSP_SPK_VOL_RMPUP_SHIFT, 1, 0), |
1232 | SOC_SINGLE("Ramp Down Switch" , MAX98396_R2092_AMP_DSP_CFG, |
1233 | MAX98396_DSP_SPK_VOL_RMPDN_SHIFT, 1, 0), |
1234 | /* Clock Monitor Enable */ |
1235 | SOC_SINGLE("CLK Monitor Switch" , MAX98396_R203F_ENABLE_CTRLS, |
1236 | MAX98396_CTRL_CMON_EN_SHIFT, 1, 0), |
1237 | /* Dither Enable */ |
1238 | SOC_SINGLE("Dither Switch" , MAX98396_R2092_AMP_DSP_CFG, |
1239 | MAX98396_DSP_SPK_DITH_EN_SHIFT, 1, 0), |
1240 | SOC_SINGLE("IV Dither Switch" , MAX98396_R20E0_IV_SENSE_PATH_CFG, |
1241 | MAX98396_IV_SENSE_DITH_EN_SHIFT, 1, 0), |
1242 | /* DC Blocker Enable */ |
1243 | SOC_SINGLE("DC Blocker Switch" , MAX98396_R2092_AMP_DSP_CFG, |
1244 | MAX98396_DSP_SPK_DCBLK_EN_SHIFT, 1, 0), |
1245 | SOC_SINGLE("IV DC Blocker Switch" , MAX98396_R20E0_IV_SENSE_PATH_CFG, |
1246 | MAX98396_IV_SENSE_DCBLK_EN_SHIFT, 3, 0), |
1247 | /* Speaker Safe Mode Enable */ |
1248 | SOC_SINGLE("Safe Mode Switch" , MAX98396_R2092_AMP_DSP_CFG, |
1249 | MAX98396_DSP_SPK_SAFE_EN_SHIFT, 1, 0), |
1250 | /* Wideband Filter Enable */ |
1251 | SOC_SINGLE("WB Filter Switch" , MAX98396_R2092_AMP_DSP_CFG, |
1252 | MAX98396_DSP_SPK_WB_FLT_EN_SHIFT, 1, 0), |
1253 | SOC_SINGLE("IV WB Filter Switch" , MAX98396_R20E0_IV_SENSE_PATH_CFG, |
1254 | MAX98396_IV_SENSE_WB_FLT_EN_SHIFT, 1, 0), |
1255 | /* Dynamic Headroom Tracking */ |
1256 | SOC_SINGLE("DHT Switch" , MAX98396_R20DF_DHT_EN, 0, 1, 0), |
1257 | /* Brownout Protection Engine */ |
1258 | SOC_SINGLE("BPE Switch" , MAX98396_R210D_BPE_EN, 0, 1, 0), |
1259 | SOC_SINGLE("BPE Limiter Switch" , MAX98396_R210D_BPE_EN, 1, 1, 0), |
1260 | /* Bypass Path Enable */ |
1261 | SOC_SINGLE("Bypass Path Switch" , |
1262 | MAX98396_R205E_PCM_RX_EN, 1, 1, 0), |
1263 | /* Speaker Operation Mode */ |
1264 | SOC_ENUM("OP Mode" , max98396_op_mod_enum), |
1265 | /* Auto Restart functions */ |
1266 | SOC_SINGLE("CMON Auto Restart Switch" , MAX98396_R2038_CLK_MON_CTRL, |
1267 | MAX98396_CLK_MON_AUTO_RESTART_SHIFT, 1, 0), |
1268 | SOC_SINGLE("PVDD Auto Restart Switch" , MAX98396_R210E_AUTO_RESTART, |
1269 | MAX98396_PVDD_UVLO_RESTART_SHFT, 1, 0), |
1270 | SOC_SINGLE("VBAT Auto Restart Switch" , MAX98396_R210E_AUTO_RESTART, |
1271 | MAX98396_VBAT_UVLO_RESTART_SHFT, 1, 0), |
1272 | SOC_SINGLE("THERM Auto Restart Switch" , MAX98396_R210E_AUTO_RESTART, |
1273 | MAX98396_THEM_SHDN_RESTART_SHFT, 1, 0), |
1274 | SOC_SINGLE("OVC Auto Restart Switch" , MAX98396_R210E_AUTO_RESTART, |
1275 | MAX98396_OVC_RESTART_SHFT, 1, 0), |
1276 | /* Thermal Threshold */ |
1277 | SOC_ENUM("THERM Thresh1" , max98396_thermal_warn_thresh1_enum), |
1278 | SOC_ENUM("THERM Thresh2" , max98396_thermal_warn_thresh2_enum), |
1279 | SOC_ENUM("THERM SHDN Thresh" , max98396_thermal_shdn_thresh_enum), |
1280 | SOC_ENUM("THERM Hysteresis" , max98396_thermal_hysteresis_enum), |
1281 | SOC_SINGLE("THERM Foldback Switch" , |
1282 | MAX98396_R2027_THERM_FOLDBACK_EN, 0, 1, 0), |
1283 | SOC_ENUM("THERM Slope1" , max98396_thermal_fb_slope1_enum), |
1284 | SOC_ENUM("THERM Slope2" , max98396_thermal_fb_slope2_enum), |
1285 | SOC_ENUM("THERM Release" , max98396_thermal_fb_reltime_enum), |
1286 | SOC_ENUM("THERM Hold" , max98396_thermal_fb_holdtime_enum), |
1287 | /* ADC */ |
1288 | SOC_SINGLE_EXT("ADC PVDD" , MAX98396_R20B6_ADC_PVDD_READBACK_MSB, 0, 0x1FF, 0, |
1289 | max98396_adc_value_get, NULL), |
1290 | SOC_SINGLE_EXT("ADC VBAT" , MAX98396_R20B8_ADC_VBAT_READBACK_MSB, 0, 0x1FF, 0, |
1291 | max98396_adc_value_get, NULL), |
1292 | SOC_SINGLE_EXT("ADC TEMP" , MAX98396_R20BA_ADC_TEMP_READBACK_MSB, 0, 0x1FF, 0, |
1293 | max98396_adc_value_get, NULL), |
1294 | }; |
1295 | |
1296 | static const struct snd_soc_dapm_route max98396_audio_map[] = { |
1297 | /* Plabyack */ |
1298 | {"DAI Sel Mux" , "Left" , "Amp Enable" }, |
1299 | {"DAI Sel Mux" , "Right" , "Amp Enable" }, |
1300 | {"DAI Sel Mux" , "LeftRight" , "Amp Enable" }, |
1301 | {"BE_OUT" , NULL, "DAI Sel Mux" }, |
1302 | /* Capture */ |
1303 | { "VI Sense" , "Switch" , "VMON" }, |
1304 | { "VI Sense" , "Switch" , "IMON" }, |
1305 | { "Voltage Sense" , NULL, "VI Sense" }, |
1306 | { "Current Sense" , NULL, "VI Sense" }, |
1307 | }; |
1308 | |
1309 | static struct snd_soc_dai_driver max98396_dai[] = { |
1310 | { |
1311 | .name = "max98396-aif1" , |
1312 | .playback = { |
1313 | .stream_name = "HiFi Playback" , |
1314 | .channels_min = 1, |
1315 | .channels_max = 2, |
1316 | .rates = MAX98396_RATES, |
1317 | .formats = MAX98396_FORMATS, |
1318 | }, |
1319 | .capture = { |
1320 | .stream_name = "HiFi Capture" , |
1321 | .channels_min = 1, |
1322 | .channels_max = 2, |
1323 | .rates = MAX98396_RATES, |
1324 | .formats = MAX98396_FORMATS, |
1325 | }, |
1326 | .ops = &max98396_dai_ops, |
1327 | } |
1328 | }; |
1329 | |
1330 | static struct snd_soc_dai_driver max98397_dai[] = { |
1331 | { |
1332 | .name = "max98397-aif1" , |
1333 | .playback = { |
1334 | .stream_name = "HiFi Playback" , |
1335 | .channels_min = 1, |
1336 | .channels_max = 2, |
1337 | .rates = MAX98396_RATES, |
1338 | .formats = MAX98396_FORMATS, |
1339 | }, |
1340 | .capture = { |
1341 | .stream_name = "HiFi Capture" , |
1342 | .channels_min = 1, |
1343 | .channels_max = 2, |
1344 | .rates = MAX98396_RATES, |
1345 | .formats = MAX98396_FORMATS, |
1346 | }, |
1347 | .ops = &max98396_dai_ops, |
1348 | } |
1349 | }; |
1350 | |
1351 | static void max98396_reset(struct max98396_priv *max98396, struct device *dev) |
1352 | { |
1353 | int ret, reg, count; |
1354 | |
1355 | /* Software Reset */ |
1356 | ret = regmap_write(map: max98396->regmap, |
1357 | MAX98396_R2000_SW_RESET, val: 1); |
1358 | if (ret) |
1359 | dev_err(dev, "Reset command failed. (ret:%d)\n" , ret); |
1360 | |
1361 | count = 0; |
1362 | while (count < 3) { |
1363 | usleep_range(min: 5000, max: 6000); |
1364 | /* Software Reset Verification */ |
1365 | ret = regmap_read(map: max98396->regmap, |
1366 | GET_REG_ADDR_REV_ID(max98396->device_id), val: ®); |
1367 | if (!ret) { |
1368 | dev_info(dev, "Reset completed (retry:%d)\n" , count); |
1369 | return; |
1370 | } |
1371 | count++; |
1372 | } |
1373 | dev_err(dev, "Reset failed. (ret:%d)\n" , ret); |
1374 | } |
1375 | |
1376 | static int max98396_probe(struct snd_soc_component *component) |
1377 | { |
1378 | struct max98396_priv *max98396 = |
1379 | snd_soc_component_get_drvdata(c: component); |
1380 | |
1381 | /* Software Reset */ |
1382 | max98396_reset(max98396, dev: component->dev); |
1383 | |
1384 | /* L/R mix configuration */ |
1385 | if (max98396->device_id == CODEC_TYPE_MAX98396) { |
1386 | regmap_write(map: max98396->regmap, |
1387 | MAX98396_R2055_PCM_RX_SRC1, val: 0x02); |
1388 | regmap_write(map: max98396->regmap, |
1389 | MAX98396_R2056_PCM_RX_SRC2, val: 0x10); |
1390 | } else { |
1391 | regmap_write(map: max98396->regmap, |
1392 | MAX98397_R2056_PCM_RX_SRC1, val: 0x02); |
1393 | regmap_write(map: max98396->regmap, |
1394 | MAX98397_R2057_PCM_RX_SRC2, val: 0x10); |
1395 | } |
1396 | /* Supply control */ |
1397 | regmap_update_bits(map: max98396->regmap, |
1398 | MAX98396_R20A0_AMP_SUPPLY_CTL, |
1399 | MAX98396_AMP_SUPPLY_NOVBAT, |
1400 | val: (max98396->vbat == NULL) ? |
1401 | MAX98396_AMP_SUPPLY_NOVBAT : 0); |
1402 | /* Enable DC blocker */ |
1403 | regmap_update_bits(map: max98396->regmap, |
1404 | MAX98396_R2092_AMP_DSP_CFG, mask: 1, val: 1); |
1405 | /* Enable IV Monitor DC blocker */ |
1406 | regmap_update_bits(map: max98396->regmap, |
1407 | MAX98396_R20E0_IV_SENSE_PATH_CFG, |
1408 | MAX98396_IV_SENSE_DCBLK_EN_MASK, |
1409 | MAX98396_IV_SENSE_DCBLK_EN_MASK); |
1410 | /* Configure default data output sources */ |
1411 | regmap_write(map: max98396->regmap, |
1412 | MAX98396_R205D_PCM_TX_SRC_EN, val: 3); |
1413 | /* Enable Wideband Filter */ |
1414 | regmap_update_bits(map: max98396->regmap, |
1415 | MAX98396_R2092_AMP_DSP_CFG, mask: 0x40, val: 0x40); |
1416 | /* Enable IV Wideband Filter */ |
1417 | regmap_update_bits(map: max98396->regmap, |
1418 | MAX98396_R20E0_IV_SENSE_PATH_CFG, mask: 8, val: 8); |
1419 | |
1420 | /* Enable Bypass Source */ |
1421 | regmap_write(map: max98396->regmap, |
1422 | MAX98396_R2058_PCM_BYPASS_SRC, |
1423 | val: max98396->bypass_slot); |
1424 | /* Voltage, current slot configuration */ |
1425 | regmap_write(map: max98396->regmap, |
1426 | MAX98396_R2044_PCM_TX_CTRL_1, |
1427 | val: max98396->v_slot); |
1428 | regmap_write(map: max98396->regmap, |
1429 | MAX98396_R2045_PCM_TX_CTRL_2, |
1430 | val: max98396->i_slot); |
1431 | regmap_write(map: max98396->regmap, |
1432 | MAX98396_R204A_PCM_TX_CTRL_7, |
1433 | val: max98396->spkfb_slot); |
1434 | |
1435 | if (max98396->v_slot < 8) |
1436 | if (max98396->device_id == CODEC_TYPE_MAX98396) |
1437 | regmap_update_bits(map: max98396->regmap, |
1438 | MAX98396_R2053_PCM_TX_HIZ_CTRL_8, |
1439 | mask: 1 << max98396->v_slot, val: 0); |
1440 | else |
1441 | regmap_update_bits(map: max98396->regmap, |
1442 | MAX98397_R2054_PCM_TX_HIZ_CTRL_8, |
1443 | mask: 1 << max98396->v_slot, val: 0); |
1444 | else |
1445 | if (max98396->device_id == CODEC_TYPE_MAX98396) |
1446 | regmap_update_bits(map: max98396->regmap, |
1447 | MAX98396_R2052_PCM_TX_HIZ_CTRL_7, |
1448 | mask: 1 << (max98396->v_slot - 8), val: 0); |
1449 | else |
1450 | regmap_update_bits(map: max98396->regmap, |
1451 | MAX98397_R2053_PCM_TX_HIZ_CTRL_7, |
1452 | mask: 1 << (max98396->v_slot - 8), val: 0); |
1453 | |
1454 | if (max98396->i_slot < 8) |
1455 | if (max98396->device_id == CODEC_TYPE_MAX98396) |
1456 | regmap_update_bits(map: max98396->regmap, |
1457 | MAX98396_R2053_PCM_TX_HIZ_CTRL_8, |
1458 | mask: 1 << max98396->i_slot, val: 0); |
1459 | else |
1460 | regmap_update_bits(map: max98396->regmap, |
1461 | MAX98397_R2054_PCM_TX_HIZ_CTRL_8, |
1462 | mask: 1 << max98396->i_slot, val: 0); |
1463 | else |
1464 | if (max98396->device_id == CODEC_TYPE_MAX98396) |
1465 | regmap_update_bits(map: max98396->regmap, |
1466 | MAX98396_R2052_PCM_TX_HIZ_CTRL_7, |
1467 | mask: 1 << (max98396->i_slot - 8), val: 0); |
1468 | else |
1469 | regmap_update_bits(map: max98396->regmap, |
1470 | MAX98397_R2053_PCM_TX_HIZ_CTRL_7, |
1471 | mask: 1 << (max98396->i_slot - 8), val: 0); |
1472 | |
1473 | /* Set interleave mode */ |
1474 | if (max98396->interleave_mode) |
1475 | regmap_update_bits(map: max98396->regmap, |
1476 | MAX98396_R2041_PCM_MODE_CFG, |
1477 | MAX98396_PCM_TX_CH_INTERLEAVE_MASK, |
1478 | MAX98396_PCM_TX_CH_INTERLEAVE_MASK); |
1479 | |
1480 | regmap_update_bits(map: max98396->regmap, |
1481 | MAX98396_R2038_CLK_MON_CTRL, |
1482 | MAX98396_CLK_MON_AUTO_RESTART_MASK, |
1483 | MAX98396_CLK_MON_AUTO_RESTART_MASK); |
1484 | |
1485 | regmap_update_bits(map: max98396->regmap, |
1486 | MAX98396_R203F_ENABLE_CTRLS, |
1487 | MAX98396_CTRL_DMON_STUCK_EN_MASK, |
1488 | val: max98396->dmon_stuck_enable ? |
1489 | MAX98396_CTRL_DMON_STUCK_EN_MASK : 0); |
1490 | |
1491 | regmap_update_bits(map: max98396->regmap, |
1492 | MAX98396_R203F_ENABLE_CTRLS, |
1493 | MAX98396_CTRL_DMON_MAG_EN_MASK, |
1494 | val: max98396->dmon_mag_enable ? |
1495 | MAX98396_CTRL_DMON_MAG_EN_MASK : 0); |
1496 | |
1497 | switch (max98396->dmon_duration) { |
1498 | case 64: |
1499 | regmap_update_bits(map: max98396->regmap, |
1500 | MAX98396_R2039_DATA_MON_CTRL, |
1501 | MAX98396_DMON_DURATION_MASK, val: 0); |
1502 | break; |
1503 | case 256: |
1504 | regmap_update_bits(map: max98396->regmap, |
1505 | MAX98396_R2039_DATA_MON_CTRL, |
1506 | MAX98396_DMON_DURATION_MASK, val: 1); |
1507 | break; |
1508 | case 1024: |
1509 | regmap_update_bits(map: max98396->regmap, |
1510 | MAX98396_R2039_DATA_MON_CTRL, |
1511 | MAX98396_DMON_DURATION_MASK, val: 2); |
1512 | break; |
1513 | case 4096: |
1514 | regmap_update_bits(map: max98396->regmap, |
1515 | MAX98396_R2039_DATA_MON_CTRL, |
1516 | MAX98396_DMON_DURATION_MASK, val: 3); |
1517 | break; |
1518 | default: |
1519 | dev_err(component->dev, "Invalid DMON duration %d\n" , |
1520 | max98396->dmon_duration); |
1521 | } |
1522 | |
1523 | switch (max98396->dmon_stuck_threshold) { |
1524 | case 15: |
1525 | regmap_update_bits(map: max98396->regmap, |
1526 | MAX98396_R2039_DATA_MON_CTRL, |
1527 | MAX98396_DMON_STUCK_THRESH_MASK, |
1528 | val: 0 << MAX98396_DMON_STUCK_THRESH_SHIFT); |
1529 | break; |
1530 | case 13: |
1531 | regmap_update_bits(map: max98396->regmap, |
1532 | MAX98396_R2039_DATA_MON_CTRL, |
1533 | MAX98396_DMON_STUCK_THRESH_MASK, |
1534 | val: 1 << MAX98396_DMON_STUCK_THRESH_SHIFT); |
1535 | break; |
1536 | case 22: |
1537 | regmap_update_bits(map: max98396->regmap, |
1538 | MAX98396_R2039_DATA_MON_CTRL, |
1539 | MAX98396_DMON_STUCK_THRESH_MASK, |
1540 | val: 2 << MAX98396_DMON_STUCK_THRESH_SHIFT); |
1541 | break; |
1542 | case 9: |
1543 | regmap_update_bits(map: max98396->regmap, |
1544 | MAX98396_R2039_DATA_MON_CTRL, |
1545 | MAX98396_DMON_STUCK_THRESH_MASK, |
1546 | val: 3 << MAX98396_DMON_STUCK_THRESH_SHIFT); |
1547 | break; |
1548 | default: |
1549 | dev_err(component->dev, "Invalid DMON stuck threshold %d\n" , |
1550 | max98396->dmon_stuck_threshold); |
1551 | } |
1552 | |
1553 | switch (max98396->dmon_mag_threshold) { |
1554 | case 2 ... 5: |
1555 | regmap_update_bits(map: max98396->regmap, |
1556 | MAX98396_R2039_DATA_MON_CTRL, |
1557 | MAX98396_DMON_STUCK_THRESH_MASK, |
1558 | val: (5 - max98396->dmon_mag_threshold) |
1559 | << MAX98396_DMON_MAG_THRESH_SHIFT); |
1560 | break; |
1561 | default: |
1562 | dev_err(component->dev, "Invalid DMON magnitude threshold %d\n" , |
1563 | max98396->dmon_mag_threshold); |
1564 | } |
1565 | |
1566 | /* Speaker Amplifier PCM RX Enable by default */ |
1567 | regmap_update_bits(map: max98396->regmap, |
1568 | MAX98396_R205E_PCM_RX_EN, |
1569 | MAX98396_PCM_RX_EN_MASK, val: 1); |
1570 | |
1571 | return 0; |
1572 | } |
1573 | |
1574 | #ifdef CONFIG_PM_SLEEP |
1575 | static int max98396_suspend(struct device *dev) |
1576 | { |
1577 | struct max98396_priv *max98396 = dev_get_drvdata(dev); |
1578 | |
1579 | regcache_cache_only(map: max98396->regmap, enable: true); |
1580 | regcache_mark_dirty(map: max98396->regmap); |
1581 | regulator_bulk_disable(MAX98396_NUM_CORE_SUPPLIES, |
1582 | consumers: max98396->core_supplies); |
1583 | if (max98396->pvdd) |
1584 | regulator_disable(regulator: max98396->pvdd); |
1585 | |
1586 | if (max98396->vbat) |
1587 | regulator_disable(regulator: max98396->vbat); |
1588 | |
1589 | return 0; |
1590 | } |
1591 | |
1592 | static int max98396_resume(struct device *dev) |
1593 | { |
1594 | struct max98396_priv *max98396 = dev_get_drvdata(dev); |
1595 | int ret; |
1596 | |
1597 | ret = regulator_bulk_enable(MAX98396_NUM_CORE_SUPPLIES, |
1598 | consumers: max98396->core_supplies); |
1599 | if (ret < 0) |
1600 | return ret; |
1601 | |
1602 | if (max98396->pvdd) { |
1603 | ret = regulator_enable(regulator: max98396->pvdd); |
1604 | if (ret < 0) |
1605 | return ret; |
1606 | } |
1607 | |
1608 | if (max98396->vbat) { |
1609 | ret = regulator_enable(regulator: max98396->vbat); |
1610 | if (ret < 0) |
1611 | return ret; |
1612 | } |
1613 | |
1614 | regcache_cache_only(map: max98396->regmap, enable: false); |
1615 | max98396_reset(max98396, dev); |
1616 | regcache_sync(map: max98396->regmap); |
1617 | return 0; |
1618 | } |
1619 | #endif |
1620 | |
1621 | static const struct dev_pm_ops max98396_pm = { |
1622 | SET_SYSTEM_SLEEP_PM_OPS(max98396_suspend, max98396_resume) |
1623 | }; |
1624 | |
1625 | static const struct snd_soc_component_driver soc_codec_dev_max98396 = { |
1626 | .probe = max98396_probe, |
1627 | .controls = max98396_snd_controls, |
1628 | .num_controls = ARRAY_SIZE(max98396_snd_controls), |
1629 | .dapm_widgets = max98396_dapm_widgets, |
1630 | .num_dapm_widgets = ARRAY_SIZE(max98396_dapm_widgets), |
1631 | .dapm_routes = max98396_audio_map, |
1632 | .num_dapm_routes = ARRAY_SIZE(max98396_audio_map), |
1633 | .idle_bias_on = 1, |
1634 | .use_pmdown_time = 1, |
1635 | .endianness = 1, |
1636 | }; |
1637 | |
1638 | static const struct snd_soc_component_driver soc_codec_dev_max98397 = { |
1639 | .probe = max98396_probe, |
1640 | .controls = max98397_snd_controls, |
1641 | .num_controls = ARRAY_SIZE(max98397_snd_controls), |
1642 | .dapm_widgets = max98396_dapm_widgets, |
1643 | .num_dapm_widgets = ARRAY_SIZE(max98396_dapm_widgets), |
1644 | .dapm_routes = max98396_audio_map, |
1645 | .num_dapm_routes = ARRAY_SIZE(max98396_audio_map), |
1646 | .idle_bias_on = 1, |
1647 | .use_pmdown_time = 1, |
1648 | .endianness = 1, |
1649 | }; |
1650 | |
1651 | static const struct regmap_config max98396_regmap = { |
1652 | .reg_bits = 16, |
1653 | .val_bits = 8, |
1654 | .max_register = MAX98396_R21FF_REVISION_ID, |
1655 | .reg_defaults = max98396_reg, |
1656 | .num_reg_defaults = ARRAY_SIZE(max98396_reg), |
1657 | .readable_reg = max98396_readable_register, |
1658 | .volatile_reg = max98396_volatile_reg, |
1659 | .cache_type = REGCACHE_RBTREE, |
1660 | }; |
1661 | |
1662 | static const struct regmap_config max98397_regmap = { |
1663 | .reg_bits = 16, |
1664 | .val_bits = 8, |
1665 | .max_register = MAX98397_R22FF_REVISION_ID, |
1666 | .reg_defaults = max98397_reg, |
1667 | .num_reg_defaults = ARRAY_SIZE(max98397_reg), |
1668 | .readable_reg = max98397_readable_register, |
1669 | .volatile_reg = max98397_volatile_reg, |
1670 | .cache_type = REGCACHE_RBTREE, |
1671 | }; |
1672 | |
1673 | static void max98396_read_device_property(struct device *dev, |
1674 | struct max98396_priv *max98396) |
1675 | { |
1676 | int value; |
1677 | |
1678 | if (!device_property_read_u32(dev, propname: "adi,vmon-slot-no" , val: &value)) |
1679 | max98396->v_slot = value & 0xF; |
1680 | else |
1681 | max98396->v_slot = 0; |
1682 | |
1683 | if (!device_property_read_u32(dev, propname: "adi,imon-slot-no" , val: &value)) |
1684 | max98396->i_slot = value & 0xF; |
1685 | else |
1686 | max98396->i_slot = 1; |
1687 | |
1688 | if (!device_property_read_u32(dev, propname: "adi,spkfb-slot-no" , val: &value)) |
1689 | max98396->spkfb_slot = value & 0xF; |
1690 | else |
1691 | max98396->spkfb_slot = 2; |
1692 | |
1693 | if (!device_property_read_u32(dev, propname: "adi,bypass-slot-no" , val: &value)) |
1694 | max98396->bypass_slot = value & 0xF; |
1695 | else |
1696 | max98396->bypass_slot = 0; |
1697 | |
1698 | max98396->dmon_stuck_enable = |
1699 | device_property_read_bool(dev, propname: "adi,dmon-stuck-enable" ); |
1700 | |
1701 | if (!device_property_read_u32(dev, propname: "adi,dmon-stuck-threshold-bits" , val: &value)) |
1702 | max98396->dmon_stuck_threshold = value; |
1703 | else |
1704 | max98396->dmon_stuck_threshold = 15; |
1705 | |
1706 | max98396->dmon_mag_enable = |
1707 | device_property_read_bool(dev, propname: "adi,dmon-magnitude-enable" ); |
1708 | |
1709 | if (!device_property_read_u32(dev, propname: "adi,dmon-magnitude-threshold-bits" , val: &value)) |
1710 | max98396->dmon_mag_threshold = value; |
1711 | else |
1712 | max98396->dmon_mag_threshold = 5; |
1713 | |
1714 | if (!device_property_read_u32(dev, propname: "adi,dmon-duration-ms" , val: &value)) |
1715 | max98396->dmon_duration = value; |
1716 | else |
1717 | max98396->dmon_duration = 64; |
1718 | } |
1719 | |
1720 | static void max98396_core_supplies_disable(void *priv) |
1721 | { |
1722 | struct max98396_priv *max98396 = priv; |
1723 | |
1724 | regulator_bulk_disable(MAX98396_NUM_CORE_SUPPLIES, |
1725 | consumers: max98396->core_supplies); |
1726 | } |
1727 | |
1728 | static void max98396_supply_disable(void *r) |
1729 | { |
1730 | regulator_disable(regulator: (struct regulator *) r); |
1731 | } |
1732 | |
1733 | static int max98396_i2c_probe(struct i2c_client *i2c) |
1734 | { |
1735 | const struct i2c_device_id *id = i2c_client_get_device_id(client: i2c); |
1736 | struct max98396_priv *max98396 = NULL; |
1737 | int i, ret, reg; |
1738 | |
1739 | max98396 = devm_kzalloc(dev: &i2c->dev, size: sizeof(*max98396), GFP_KERNEL); |
1740 | |
1741 | if (!max98396) { |
1742 | ret = -ENOMEM; |
1743 | return ret; |
1744 | } |
1745 | i2c_set_clientdata(client: i2c, data: max98396); |
1746 | |
1747 | max98396->device_id = id->driver_data; |
1748 | |
1749 | /* regmap initialization */ |
1750 | if (max98396->device_id == CODEC_TYPE_MAX98396) |
1751 | max98396->regmap = devm_regmap_init_i2c(i2c, &max98396_regmap); |
1752 | |
1753 | else |
1754 | max98396->regmap = devm_regmap_init_i2c(i2c, &max98397_regmap); |
1755 | |
1756 | if (IS_ERR(ptr: max98396->regmap)) { |
1757 | ret = PTR_ERR(ptr: max98396->regmap); |
1758 | dev_err(&i2c->dev, |
1759 | "Failed to allocate regmap: %d\n" , ret); |
1760 | return ret; |
1761 | } |
1762 | |
1763 | /* Obtain regulator supplies */ |
1764 | for (i = 0; i < MAX98396_NUM_CORE_SUPPLIES; i++) |
1765 | max98396->core_supplies[i].supply = max98396_core_supplies[i]; |
1766 | |
1767 | ret = devm_regulator_bulk_get(dev: &i2c->dev, MAX98396_NUM_CORE_SUPPLIES, |
1768 | consumers: max98396->core_supplies); |
1769 | if (ret < 0) { |
1770 | dev_err(&i2c->dev, "Failed to request core supplies: %d\n" , ret); |
1771 | return ret; |
1772 | } |
1773 | |
1774 | max98396->vbat = devm_regulator_get_optional(dev: &i2c->dev, id: "vbat" ); |
1775 | if (IS_ERR(ptr: max98396->vbat)) { |
1776 | if (PTR_ERR(ptr: max98396->vbat) == -EPROBE_DEFER) |
1777 | return -EPROBE_DEFER; |
1778 | |
1779 | max98396->vbat = NULL; |
1780 | } |
1781 | |
1782 | max98396->pvdd = devm_regulator_get_optional(dev: &i2c->dev, id: "pvdd" ); |
1783 | if (IS_ERR(ptr: max98396->pvdd)) { |
1784 | if (PTR_ERR(ptr: max98396->pvdd) == -EPROBE_DEFER) |
1785 | return -EPROBE_DEFER; |
1786 | |
1787 | max98396->pvdd = NULL; |
1788 | } |
1789 | |
1790 | ret = regulator_bulk_enable(MAX98396_NUM_CORE_SUPPLIES, |
1791 | consumers: max98396->core_supplies); |
1792 | if (ret < 0) { |
1793 | dev_err(&i2c->dev, "Unable to enable core supplies: %d" , ret); |
1794 | return ret; |
1795 | } |
1796 | |
1797 | ret = devm_add_action_or_reset(&i2c->dev, max98396_core_supplies_disable, |
1798 | max98396); |
1799 | if (ret < 0) |
1800 | return ret; |
1801 | |
1802 | if (max98396->pvdd) { |
1803 | ret = regulator_enable(regulator: max98396->pvdd); |
1804 | if (ret < 0) |
1805 | return ret; |
1806 | |
1807 | ret = devm_add_action_or_reset(&i2c->dev, |
1808 | max98396_supply_disable, |
1809 | max98396->pvdd); |
1810 | if (ret < 0) |
1811 | return ret; |
1812 | } |
1813 | |
1814 | if (max98396->vbat) { |
1815 | ret = regulator_enable(regulator: max98396->vbat); |
1816 | if (ret < 0) |
1817 | return ret; |
1818 | |
1819 | ret = devm_add_action_or_reset(&i2c->dev, |
1820 | max98396_supply_disable, |
1821 | max98396->vbat); |
1822 | if (ret < 0) |
1823 | return ret; |
1824 | } |
1825 | |
1826 | /* update interleave mode info */ |
1827 | if (device_property_read_bool(dev: &i2c->dev, propname: "adi,interleave_mode" )) |
1828 | max98396->interleave_mode = true; |
1829 | else |
1830 | max98396->interleave_mode = false; |
1831 | |
1832 | /* voltage/current slot & gpio configuration */ |
1833 | max98396_read_device_property(dev: &i2c->dev, max98396); |
1834 | |
1835 | /* Reset the Device */ |
1836 | max98396->reset_gpio = devm_gpiod_get_optional(dev: &i2c->dev, |
1837 | con_id: "reset" , flags: GPIOD_OUT_HIGH); |
1838 | if (IS_ERR(ptr: max98396->reset_gpio)) { |
1839 | ret = PTR_ERR(ptr: max98396->reset_gpio); |
1840 | dev_err(&i2c->dev, "Unable to request GPIO pin: %d.\n" , ret); |
1841 | return ret; |
1842 | } |
1843 | |
1844 | if (max98396->reset_gpio) { |
1845 | usleep_range(min: 5000, max: 6000); |
1846 | gpiod_set_value_cansleep(desc: max98396->reset_gpio, value: 0); |
1847 | /* Wait for the hw reset done */ |
1848 | usleep_range(min: 5000, max: 6000); |
1849 | } |
1850 | |
1851 | ret = regmap_read(map: max98396->regmap, |
1852 | GET_REG_ADDR_REV_ID(max98396->device_id), val: ®); |
1853 | if (ret < 0) { |
1854 | dev_err(&i2c->dev, "%s: failed to read revision of the device.\n" , id->name); |
1855 | return ret; |
1856 | } |
1857 | dev_info(&i2c->dev, "%s revision ID: 0x%02X\n" , id->name, reg); |
1858 | |
1859 | /* codec registration */ |
1860 | if (max98396->device_id == CODEC_TYPE_MAX98396) |
1861 | ret = devm_snd_soc_register_component(dev: &i2c->dev, |
1862 | component_driver: &soc_codec_dev_max98396, |
1863 | dai_drv: max98396_dai, |
1864 | ARRAY_SIZE(max98396_dai)); |
1865 | else |
1866 | ret = devm_snd_soc_register_component(dev: &i2c->dev, |
1867 | component_driver: &soc_codec_dev_max98397, |
1868 | dai_drv: max98397_dai, |
1869 | ARRAY_SIZE(max98397_dai)); |
1870 | if (ret < 0) |
1871 | dev_err(&i2c->dev, "Failed to register codec: %d\n" , ret); |
1872 | |
1873 | return ret; |
1874 | } |
1875 | |
1876 | static const struct i2c_device_id max98396_i2c_id[] = { |
1877 | { "max98396" , CODEC_TYPE_MAX98396}, |
1878 | { "max98397" , CODEC_TYPE_MAX98397}, |
1879 | { }, |
1880 | }; |
1881 | |
1882 | MODULE_DEVICE_TABLE(i2c, max98396_i2c_id); |
1883 | |
1884 | #if defined(CONFIG_OF) |
1885 | static const struct of_device_id max98396_of_match[] = { |
1886 | { .compatible = "adi,max98396" , }, |
1887 | { .compatible = "adi,max98397" , }, |
1888 | { } |
1889 | }; |
1890 | MODULE_DEVICE_TABLE(of, max98396_of_match); |
1891 | #endif |
1892 | |
1893 | #ifdef CONFIG_ACPI |
1894 | static const struct acpi_device_id max98396_acpi_match[] = { |
1895 | { "ADS8396" , 0 }, |
1896 | { "ADS8397" , 0 }, |
1897 | {}, |
1898 | }; |
1899 | MODULE_DEVICE_TABLE(acpi, max98396_acpi_match); |
1900 | #endif |
1901 | |
1902 | static struct i2c_driver max98396_i2c_driver = { |
1903 | .driver = { |
1904 | .name = "max98396" , |
1905 | .of_match_table = of_match_ptr(max98396_of_match), |
1906 | .acpi_match_table = ACPI_PTR(max98396_acpi_match), |
1907 | .pm = &max98396_pm, |
1908 | }, |
1909 | .probe = max98396_i2c_probe, |
1910 | .id_table = max98396_i2c_id, |
1911 | }; |
1912 | |
1913 | module_i2c_driver(max98396_i2c_driver) |
1914 | |
1915 | MODULE_DESCRIPTION("ALSA SoC MAX98396 driver" ); |
1916 | MODULE_AUTHOR("Ryan Lee <ryans.lee@analog.com>" ); |
1917 | MODULE_LICENSE("GPL" ); |
1918 | |