1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* |
3 | * max98088.c -- MAX98088 ALSA SoC Audio driver |
4 | * |
5 | * Copyright 2010 Maxim Integrated Products |
6 | */ |
7 | |
8 | #include <linux/module.h> |
9 | #include <linux/moduleparam.h> |
10 | #include <linux/kernel.h> |
11 | #include <linux/init.h> |
12 | #include <linux/delay.h> |
13 | #include <linux/pm.h> |
14 | #include <linux/i2c.h> |
15 | #include <linux/regmap.h> |
16 | #include <linux/clk.h> |
17 | #include <sound/core.h> |
18 | #include <sound/pcm.h> |
19 | #include <sound/pcm_params.h> |
20 | #include <sound/soc.h> |
21 | #include <sound/initval.h> |
22 | #include <sound/tlv.h> |
23 | #include <linux/slab.h> |
24 | #include <asm/div64.h> |
25 | #include <sound/max98088.h> |
26 | #include "max98088.h" |
27 | |
28 | enum max98088_type { |
29 | MAX98088, |
30 | MAX98089, |
31 | }; |
32 | |
33 | struct max98088_cdata { |
34 | unsigned int rate; |
35 | unsigned int fmt; |
36 | int eq_sel; |
37 | }; |
38 | |
39 | struct max98088_priv { |
40 | struct regmap *regmap; |
41 | enum max98088_type devtype; |
42 | struct max98088_pdata *pdata; |
43 | struct clk *mclk; |
44 | unsigned char mclk_prescaler; |
45 | unsigned int sysclk; |
46 | struct max98088_cdata dai[2]; |
47 | int eq_textcnt; |
48 | const char **eq_texts; |
49 | struct soc_enum eq_enum; |
50 | u8 ina_state; |
51 | u8 inb_state; |
52 | unsigned int ex_mode; |
53 | unsigned int digmic; |
54 | unsigned int mic1pre; |
55 | unsigned int mic2pre; |
56 | unsigned int extmic_mode; |
57 | }; |
58 | |
59 | static const struct reg_default max98088_reg[] = { |
60 | { 0xf, 0x00 }, /* 0F interrupt enable */ |
61 | |
62 | { 0x10, 0x00 }, /* 10 master clock */ |
63 | { 0x11, 0x00 }, /* 11 DAI1 clock mode */ |
64 | { 0x12, 0x00 }, /* 12 DAI1 clock control */ |
65 | { 0x13, 0x00 }, /* 13 DAI1 clock control */ |
66 | { 0x14, 0x00 }, /* 14 DAI1 format */ |
67 | { 0x15, 0x00 }, /* 15 DAI1 clock */ |
68 | { 0x16, 0x00 }, /* 16 DAI1 config */ |
69 | { 0x17, 0x00 }, /* 17 DAI1 TDM */ |
70 | { 0x18, 0x00 }, /* 18 DAI1 filters */ |
71 | { 0x19, 0x00 }, /* 19 DAI2 clock mode */ |
72 | { 0x1a, 0x00 }, /* 1A DAI2 clock control */ |
73 | { 0x1b, 0x00 }, /* 1B DAI2 clock control */ |
74 | { 0x1c, 0x00 }, /* 1C DAI2 format */ |
75 | { 0x1d, 0x00 }, /* 1D DAI2 clock */ |
76 | { 0x1e, 0x00 }, /* 1E DAI2 config */ |
77 | { 0x1f, 0x00 }, /* 1F DAI2 TDM */ |
78 | |
79 | { 0x20, 0x00 }, /* 20 DAI2 filters */ |
80 | { 0x21, 0x00 }, /* 21 data config */ |
81 | { 0x22, 0x00 }, /* 22 DAC mixer */ |
82 | { 0x23, 0x00 }, /* 23 left ADC mixer */ |
83 | { 0x24, 0x00 }, /* 24 right ADC mixer */ |
84 | { 0x25, 0x00 }, /* 25 left HP mixer */ |
85 | { 0x26, 0x00 }, /* 26 right HP mixer */ |
86 | { 0x27, 0x00 }, /* 27 HP control */ |
87 | { 0x28, 0x00 }, /* 28 left REC mixer */ |
88 | { 0x29, 0x00 }, /* 29 right REC mixer */ |
89 | { 0x2a, 0x00 }, /* 2A REC control */ |
90 | { 0x2b, 0x00 }, /* 2B left SPK mixer */ |
91 | { 0x2c, 0x00 }, /* 2C right SPK mixer */ |
92 | { 0x2d, 0x00 }, /* 2D SPK control */ |
93 | { 0x2e, 0x00 }, /* 2E sidetone */ |
94 | { 0x2f, 0x00 }, /* 2F DAI1 playback level */ |
95 | |
96 | { 0x30, 0x00 }, /* 30 DAI1 playback level */ |
97 | { 0x31, 0x00 }, /* 31 DAI2 playback level */ |
98 | { 0x32, 0x00 }, /* 32 DAI2 playbakc level */ |
99 | { 0x33, 0x00 }, /* 33 left ADC level */ |
100 | { 0x34, 0x00 }, /* 34 right ADC level */ |
101 | { 0x35, 0x00 }, /* 35 MIC1 level */ |
102 | { 0x36, 0x00 }, /* 36 MIC2 level */ |
103 | { 0x37, 0x00 }, /* 37 INA level */ |
104 | { 0x38, 0x00 }, /* 38 INB level */ |
105 | { 0x39, 0x00 }, /* 39 left HP volume */ |
106 | { 0x3a, 0x00 }, /* 3A right HP volume */ |
107 | { 0x3b, 0x00 }, /* 3B left REC volume */ |
108 | { 0x3c, 0x00 }, /* 3C right REC volume */ |
109 | { 0x3d, 0x00 }, /* 3D left SPK volume */ |
110 | { 0x3e, 0x00 }, /* 3E right SPK volume */ |
111 | { 0x3f, 0x00 }, /* 3F MIC config */ |
112 | |
113 | { 0x40, 0x00 }, /* 40 MIC threshold */ |
114 | { 0x41, 0x00 }, /* 41 excursion limiter filter */ |
115 | { 0x42, 0x00 }, /* 42 excursion limiter threshold */ |
116 | { 0x43, 0x00 }, /* 43 ALC */ |
117 | { 0x44, 0x00 }, /* 44 power limiter threshold */ |
118 | { 0x45, 0x00 }, /* 45 power limiter config */ |
119 | { 0x46, 0x00 }, /* 46 distortion limiter config */ |
120 | { 0x47, 0x00 }, /* 47 audio input */ |
121 | { 0x48, 0x00 }, /* 48 microphone */ |
122 | { 0x49, 0x00 }, /* 49 level control */ |
123 | { 0x4a, 0x00 }, /* 4A bypass switches */ |
124 | { 0x4b, 0x00 }, /* 4B jack detect */ |
125 | { 0x4c, 0x00 }, /* 4C input enable */ |
126 | { 0x4d, 0x00 }, /* 4D output enable */ |
127 | { 0x4e, 0xF0 }, /* 4E bias control */ |
128 | { 0x4f, 0x00 }, /* 4F DAC power */ |
129 | |
130 | { 0x50, 0x0F }, /* 50 DAC power */ |
131 | { 0x51, 0x00 }, /* 51 system */ |
132 | { 0x52, 0x00 }, /* 52 DAI1 EQ1 */ |
133 | { 0x53, 0x00 }, /* 53 DAI1 EQ1 */ |
134 | { 0x54, 0x00 }, /* 54 DAI1 EQ1 */ |
135 | { 0x55, 0x00 }, /* 55 DAI1 EQ1 */ |
136 | { 0x56, 0x00 }, /* 56 DAI1 EQ1 */ |
137 | { 0x57, 0x00 }, /* 57 DAI1 EQ1 */ |
138 | { 0x58, 0x00 }, /* 58 DAI1 EQ1 */ |
139 | { 0x59, 0x00 }, /* 59 DAI1 EQ1 */ |
140 | { 0x5a, 0x00 }, /* 5A DAI1 EQ1 */ |
141 | { 0x5b, 0x00 }, /* 5B DAI1 EQ1 */ |
142 | { 0x5c, 0x00 }, /* 5C DAI1 EQ2 */ |
143 | { 0x5d, 0x00 }, /* 5D DAI1 EQ2 */ |
144 | { 0x5e, 0x00 }, /* 5E DAI1 EQ2 */ |
145 | { 0x5f, 0x00 }, /* 5F DAI1 EQ2 */ |
146 | |
147 | { 0x60, 0x00 }, /* 60 DAI1 EQ2 */ |
148 | { 0x61, 0x00 }, /* 61 DAI1 EQ2 */ |
149 | { 0x62, 0x00 }, /* 62 DAI1 EQ2 */ |
150 | { 0x63, 0x00 }, /* 63 DAI1 EQ2 */ |
151 | { 0x64, 0x00 }, /* 64 DAI1 EQ2 */ |
152 | { 0x65, 0x00 }, /* 65 DAI1 EQ2 */ |
153 | { 0x66, 0x00 }, /* 66 DAI1 EQ3 */ |
154 | { 0x67, 0x00 }, /* 67 DAI1 EQ3 */ |
155 | { 0x68, 0x00 }, /* 68 DAI1 EQ3 */ |
156 | { 0x69, 0x00 }, /* 69 DAI1 EQ3 */ |
157 | { 0x6a, 0x00 }, /* 6A DAI1 EQ3 */ |
158 | { 0x6b, 0x00 }, /* 6B DAI1 EQ3 */ |
159 | { 0x6c, 0x00 }, /* 6C DAI1 EQ3 */ |
160 | { 0x6d, 0x00 }, /* 6D DAI1 EQ3 */ |
161 | { 0x6e, 0x00 }, /* 6E DAI1 EQ3 */ |
162 | { 0x6f, 0x00 }, /* 6F DAI1 EQ3 */ |
163 | |
164 | { 0x70, 0x00 }, /* 70 DAI1 EQ4 */ |
165 | { 0x71, 0x00 }, /* 71 DAI1 EQ4 */ |
166 | { 0x72, 0x00 }, /* 72 DAI1 EQ4 */ |
167 | { 0x73, 0x00 }, /* 73 DAI1 EQ4 */ |
168 | { 0x74, 0x00 }, /* 74 DAI1 EQ4 */ |
169 | { 0x75, 0x00 }, /* 75 DAI1 EQ4 */ |
170 | { 0x76, 0x00 }, /* 76 DAI1 EQ4 */ |
171 | { 0x77, 0x00 }, /* 77 DAI1 EQ4 */ |
172 | { 0x78, 0x00 }, /* 78 DAI1 EQ4 */ |
173 | { 0x79, 0x00 }, /* 79 DAI1 EQ4 */ |
174 | { 0x7a, 0x00 }, /* 7A DAI1 EQ5 */ |
175 | { 0x7b, 0x00 }, /* 7B DAI1 EQ5 */ |
176 | { 0x7c, 0x00 }, /* 7C DAI1 EQ5 */ |
177 | { 0x7d, 0x00 }, /* 7D DAI1 EQ5 */ |
178 | { 0x7e, 0x00 }, /* 7E DAI1 EQ5 */ |
179 | { 0x7f, 0x00 }, /* 7F DAI1 EQ5 */ |
180 | |
181 | { 0x80, 0x00 }, /* 80 DAI1 EQ5 */ |
182 | { 0x81, 0x00 }, /* 81 DAI1 EQ5 */ |
183 | { 0x82, 0x00 }, /* 82 DAI1 EQ5 */ |
184 | { 0x83, 0x00 }, /* 83 DAI1 EQ5 */ |
185 | { 0x84, 0x00 }, /* 84 DAI2 EQ1 */ |
186 | { 0x85, 0x00 }, /* 85 DAI2 EQ1 */ |
187 | { 0x86, 0x00 }, /* 86 DAI2 EQ1 */ |
188 | { 0x87, 0x00 }, /* 87 DAI2 EQ1 */ |
189 | { 0x88, 0x00 }, /* 88 DAI2 EQ1 */ |
190 | { 0x89, 0x00 }, /* 89 DAI2 EQ1 */ |
191 | { 0x8a, 0x00 }, /* 8A DAI2 EQ1 */ |
192 | { 0x8b, 0x00 }, /* 8B DAI2 EQ1 */ |
193 | { 0x8c, 0x00 }, /* 8C DAI2 EQ1 */ |
194 | { 0x8d, 0x00 }, /* 8D DAI2 EQ1 */ |
195 | { 0x8e, 0x00 }, /* 8E DAI2 EQ2 */ |
196 | { 0x8f, 0x00 }, /* 8F DAI2 EQ2 */ |
197 | |
198 | { 0x90, 0x00 }, /* 90 DAI2 EQ2 */ |
199 | { 0x91, 0x00 }, /* 91 DAI2 EQ2 */ |
200 | { 0x92, 0x00 }, /* 92 DAI2 EQ2 */ |
201 | { 0x93, 0x00 }, /* 93 DAI2 EQ2 */ |
202 | { 0x94, 0x00 }, /* 94 DAI2 EQ2 */ |
203 | { 0x95, 0x00 }, /* 95 DAI2 EQ2 */ |
204 | { 0x96, 0x00 }, /* 96 DAI2 EQ2 */ |
205 | { 0x97, 0x00 }, /* 97 DAI2 EQ2 */ |
206 | { 0x98, 0x00 }, /* 98 DAI2 EQ3 */ |
207 | { 0x99, 0x00 }, /* 99 DAI2 EQ3 */ |
208 | { 0x9a, 0x00 }, /* 9A DAI2 EQ3 */ |
209 | { 0x9b, 0x00 }, /* 9B DAI2 EQ3 */ |
210 | { 0x9c, 0x00 }, /* 9C DAI2 EQ3 */ |
211 | { 0x9d, 0x00 }, /* 9D DAI2 EQ3 */ |
212 | { 0x9e, 0x00 }, /* 9E DAI2 EQ3 */ |
213 | { 0x9f, 0x00 }, /* 9F DAI2 EQ3 */ |
214 | |
215 | { 0xa0, 0x00 }, /* A0 DAI2 EQ3 */ |
216 | { 0xa1, 0x00 }, /* A1 DAI2 EQ3 */ |
217 | { 0xa2, 0x00 }, /* A2 DAI2 EQ4 */ |
218 | { 0xa3, 0x00 }, /* A3 DAI2 EQ4 */ |
219 | { 0xa4, 0x00 }, /* A4 DAI2 EQ4 */ |
220 | { 0xa5, 0x00 }, /* A5 DAI2 EQ4 */ |
221 | { 0xa6, 0x00 }, /* A6 DAI2 EQ4 */ |
222 | { 0xa7, 0x00 }, /* A7 DAI2 EQ4 */ |
223 | { 0xa8, 0x00 }, /* A8 DAI2 EQ4 */ |
224 | { 0xa9, 0x00 }, /* A9 DAI2 EQ4 */ |
225 | { 0xaa, 0x00 }, /* AA DAI2 EQ4 */ |
226 | { 0xab, 0x00 }, /* AB DAI2 EQ4 */ |
227 | { 0xac, 0x00 }, /* AC DAI2 EQ5 */ |
228 | { 0xad, 0x00 }, /* AD DAI2 EQ5 */ |
229 | { 0xae, 0x00 }, /* AE DAI2 EQ5 */ |
230 | { 0xaf, 0x00 }, /* AF DAI2 EQ5 */ |
231 | |
232 | { 0xb0, 0x00 }, /* B0 DAI2 EQ5 */ |
233 | { 0xb1, 0x00 }, /* B1 DAI2 EQ5 */ |
234 | { 0xb2, 0x00 }, /* B2 DAI2 EQ5 */ |
235 | { 0xb3, 0x00 }, /* B3 DAI2 EQ5 */ |
236 | { 0xb4, 0x00 }, /* B4 DAI2 EQ5 */ |
237 | { 0xb5, 0x00 }, /* B5 DAI2 EQ5 */ |
238 | { 0xb6, 0x00 }, /* B6 DAI1 biquad */ |
239 | { 0xb7, 0x00 }, /* B7 DAI1 biquad */ |
240 | { 0xb8 ,0x00 }, /* B8 DAI1 biquad */ |
241 | { 0xb9, 0x00 }, /* B9 DAI1 biquad */ |
242 | { 0xba, 0x00 }, /* BA DAI1 biquad */ |
243 | { 0xbb, 0x00 }, /* BB DAI1 biquad */ |
244 | { 0xbc, 0x00 }, /* BC DAI1 biquad */ |
245 | { 0xbd, 0x00 }, /* BD DAI1 biquad */ |
246 | { 0xbe, 0x00 }, /* BE DAI1 biquad */ |
247 | { 0xbf, 0x00 }, /* BF DAI1 biquad */ |
248 | |
249 | { 0xc0, 0x00 }, /* C0 DAI2 biquad */ |
250 | { 0xc1, 0x00 }, /* C1 DAI2 biquad */ |
251 | { 0xc2, 0x00 }, /* C2 DAI2 biquad */ |
252 | { 0xc3, 0x00 }, /* C3 DAI2 biquad */ |
253 | { 0xc4, 0x00 }, /* C4 DAI2 biquad */ |
254 | { 0xc5, 0x00 }, /* C5 DAI2 biquad */ |
255 | { 0xc6, 0x00 }, /* C6 DAI2 biquad */ |
256 | { 0xc7, 0x00 }, /* C7 DAI2 biquad */ |
257 | { 0xc8, 0x00 }, /* C8 DAI2 biquad */ |
258 | { 0xc9, 0x00 }, /* C9 DAI2 biquad */ |
259 | }; |
260 | |
261 | static bool max98088_readable_register(struct device *dev, unsigned int reg) |
262 | { |
263 | switch (reg) { |
264 | case M98088_REG_00_IRQ_STATUS ... 0xC9: |
265 | case M98088_REG_FF_REV_ID: |
266 | return true; |
267 | default: |
268 | return false; |
269 | } |
270 | } |
271 | |
272 | static bool max98088_writeable_register(struct device *dev, unsigned int reg) |
273 | { |
274 | switch (reg) { |
275 | case M98088_REG_03_BATTERY_VOLTAGE ... 0xC9: |
276 | return true; |
277 | default: |
278 | return false; |
279 | } |
280 | } |
281 | |
282 | static bool max98088_volatile_register(struct device *dev, unsigned int reg) |
283 | { |
284 | switch (reg) { |
285 | case M98088_REG_00_IRQ_STATUS ... M98088_REG_03_BATTERY_VOLTAGE: |
286 | case M98088_REG_FF_REV_ID: |
287 | return true; |
288 | default: |
289 | return false; |
290 | } |
291 | } |
292 | |
293 | static const struct regmap_config max98088_regmap = { |
294 | .reg_bits = 8, |
295 | .val_bits = 8, |
296 | |
297 | .readable_reg = max98088_readable_register, |
298 | .writeable_reg = max98088_writeable_register, |
299 | .volatile_reg = max98088_volatile_register, |
300 | .max_register = 0xff, |
301 | |
302 | .reg_defaults = max98088_reg, |
303 | .num_reg_defaults = ARRAY_SIZE(max98088_reg), |
304 | .cache_type = REGCACHE_RBTREE, |
305 | }; |
306 | |
307 | /* |
308 | * Load equalizer DSP coefficient configurations registers |
309 | */ |
310 | static void m98088_eq_band(struct snd_soc_component *component, unsigned int dai, |
311 | unsigned int band, u16 *coefs) |
312 | { |
313 | unsigned int eq_reg; |
314 | unsigned int i; |
315 | |
316 | if (WARN_ON(band > 4) || |
317 | WARN_ON(dai > 1)) |
318 | return; |
319 | |
320 | /* Load the base register address */ |
321 | eq_reg = dai ? M98088_REG_84_DAI2_EQ_BASE : M98088_REG_52_DAI1_EQ_BASE; |
322 | |
323 | /* Add the band address offset, note adjustment for word address */ |
324 | eq_reg += band * (M98088_COEFS_PER_BAND << 1); |
325 | |
326 | /* Step through the registers and coefs */ |
327 | for (i = 0; i < M98088_COEFS_PER_BAND; i++) { |
328 | snd_soc_component_write(component, reg: eq_reg++, M98088_BYTE1(coefs[i])); |
329 | snd_soc_component_write(component, reg: eq_reg++, M98088_BYTE0(coefs[i])); |
330 | } |
331 | } |
332 | |
333 | /* |
334 | * Excursion limiter modes |
335 | */ |
336 | static const char *max98088_exmode_texts[] = { |
337 | "Off" , "100Hz" , "400Hz" , "600Hz" , "800Hz" , "1000Hz" , "200-400Hz" , |
338 | "400-600Hz" , "400-800Hz" , |
339 | }; |
340 | |
341 | static const unsigned int max98088_exmode_values[] = { |
342 | 0x00, 0x43, 0x10, 0x20, 0x30, 0x40, 0x11, 0x22, 0x32 |
343 | }; |
344 | |
345 | static SOC_VALUE_ENUM_SINGLE_DECL(max98088_exmode_enum, |
346 | M98088_REG_41_SPKDHP, 0, 127, |
347 | max98088_exmode_texts, |
348 | max98088_exmode_values); |
349 | |
350 | static const char *max98088_ex_thresh[] = { /* volts PP */ |
351 | "0.6" , "1.2" , "1.8" , "2.4" , "3.0" , "3.6" , "4.2" , "4.8" }; |
352 | static SOC_ENUM_SINGLE_DECL(max98088_ex_thresh_enum, |
353 | M98088_REG_42_SPKDHP_THRESH, 0, |
354 | max98088_ex_thresh); |
355 | |
356 | static const char *max98088_fltr_mode[] = {"Voice" , "Music" }; |
357 | static SOC_ENUM_SINGLE_DECL(max98088_filter_mode_enum, |
358 | M98088_REG_18_DAI1_FILTERS, 7, |
359 | max98088_fltr_mode); |
360 | |
361 | static const char *max98088_extmic_text[] = { "None" , "MIC1" , "MIC2" }; |
362 | |
363 | static SOC_ENUM_SINGLE_DECL(max98088_extmic_enum, |
364 | M98088_REG_48_CFG_MIC, 0, |
365 | max98088_extmic_text); |
366 | |
367 | static const struct snd_kcontrol_new max98088_extmic_mux = |
368 | SOC_DAPM_ENUM("External MIC Mux" , max98088_extmic_enum); |
369 | |
370 | static const char *max98088_dai1_fltr[] = { |
371 | "Off" , "fc=258/fs=16k" , "fc=500/fs=16k" , |
372 | "fc=258/fs=8k" , "fc=500/fs=8k" , "fc=200" }; |
373 | static SOC_ENUM_SINGLE_DECL(max98088_dai1_dac_filter_enum, |
374 | M98088_REG_18_DAI1_FILTERS, 0, |
375 | max98088_dai1_fltr); |
376 | static SOC_ENUM_SINGLE_DECL(max98088_dai1_adc_filter_enum, |
377 | M98088_REG_18_DAI1_FILTERS, 4, |
378 | max98088_dai1_fltr); |
379 | |
380 | static int max98088_mic1pre_set(struct snd_kcontrol *kcontrol, |
381 | struct snd_ctl_elem_value *ucontrol) |
382 | { |
383 | struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); |
384 | struct max98088_priv *max98088 = snd_soc_component_get_drvdata(c: component); |
385 | unsigned int sel = ucontrol->value.integer.value[0]; |
386 | |
387 | max98088->mic1pre = sel; |
388 | snd_soc_component_update_bits(component, M98088_REG_35_LVL_MIC1, M98088_MICPRE_MASK, |
389 | val: (1+sel)<<M98088_MICPRE_SHIFT); |
390 | |
391 | return 0; |
392 | } |
393 | |
394 | static int max98088_mic1pre_get(struct snd_kcontrol *kcontrol, |
395 | struct snd_ctl_elem_value *ucontrol) |
396 | { |
397 | struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); |
398 | struct max98088_priv *max98088 = snd_soc_component_get_drvdata(c: component); |
399 | |
400 | ucontrol->value.integer.value[0] = max98088->mic1pre; |
401 | return 0; |
402 | } |
403 | |
404 | static int max98088_mic2pre_set(struct snd_kcontrol *kcontrol, |
405 | struct snd_ctl_elem_value *ucontrol) |
406 | { |
407 | struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); |
408 | struct max98088_priv *max98088 = snd_soc_component_get_drvdata(c: component); |
409 | unsigned int sel = ucontrol->value.integer.value[0]; |
410 | |
411 | max98088->mic2pre = sel; |
412 | snd_soc_component_update_bits(component, M98088_REG_36_LVL_MIC2, M98088_MICPRE_MASK, |
413 | val: (1+sel)<<M98088_MICPRE_SHIFT); |
414 | |
415 | return 0; |
416 | } |
417 | |
418 | static int max98088_mic2pre_get(struct snd_kcontrol *kcontrol, |
419 | struct snd_ctl_elem_value *ucontrol) |
420 | { |
421 | struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); |
422 | struct max98088_priv *max98088 = snd_soc_component_get_drvdata(c: component); |
423 | |
424 | ucontrol->value.integer.value[0] = max98088->mic2pre; |
425 | return 0; |
426 | } |
427 | |
428 | static const DECLARE_TLV_DB_RANGE(max98088_micboost_tlv, |
429 | 0, 1, TLV_DB_SCALE_ITEM(0, 2000, 0), |
430 | 2, 2, TLV_DB_SCALE_ITEM(3000, 0, 0) |
431 | ); |
432 | |
433 | static const DECLARE_TLV_DB_RANGE(max98088_hp_tlv, |
434 | 0, 6, TLV_DB_SCALE_ITEM(-6700, 400, 0), |
435 | 7, 14, TLV_DB_SCALE_ITEM(-4000, 300, 0), |
436 | 15, 21, TLV_DB_SCALE_ITEM(-1700, 200, 0), |
437 | 22, 27, TLV_DB_SCALE_ITEM(-400, 100, 0), |
438 | 28, 31, TLV_DB_SCALE_ITEM(150, 50, 0) |
439 | ); |
440 | |
441 | static const DECLARE_TLV_DB_RANGE(max98088_spk_tlv, |
442 | 0, 6, TLV_DB_SCALE_ITEM(-6200, 400, 0), |
443 | 7, 14, TLV_DB_SCALE_ITEM(-3500, 300, 0), |
444 | 15, 21, TLV_DB_SCALE_ITEM(-1200, 200, 0), |
445 | 22, 27, TLV_DB_SCALE_ITEM(100, 100, 0), |
446 | 28, 31, TLV_DB_SCALE_ITEM(650, 50, 0) |
447 | ); |
448 | |
449 | static const struct snd_kcontrol_new max98088_snd_controls[] = { |
450 | |
451 | SOC_DOUBLE_R_TLV("Headphone Volume" , M98088_REG_39_LVL_HP_L, |
452 | M98088_REG_3A_LVL_HP_R, 0, 31, 0, max98088_hp_tlv), |
453 | SOC_DOUBLE_R_TLV("Speaker Volume" , M98088_REG_3D_LVL_SPK_L, |
454 | M98088_REG_3E_LVL_SPK_R, 0, 31, 0, max98088_spk_tlv), |
455 | SOC_DOUBLE_R_TLV("Receiver Volume" , M98088_REG_3B_LVL_REC_L, |
456 | M98088_REG_3C_LVL_REC_R, 0, 31, 0, max98088_spk_tlv), |
457 | |
458 | SOC_DOUBLE_R("Headphone Switch" , M98088_REG_39_LVL_HP_L, |
459 | M98088_REG_3A_LVL_HP_R, 7, 1, 1), |
460 | SOC_DOUBLE_R("Speaker Switch" , M98088_REG_3D_LVL_SPK_L, |
461 | M98088_REG_3E_LVL_SPK_R, 7, 1, 1), |
462 | SOC_DOUBLE_R("Receiver Switch" , M98088_REG_3B_LVL_REC_L, |
463 | M98088_REG_3C_LVL_REC_R, 7, 1, 1), |
464 | |
465 | SOC_SINGLE("MIC1 Volume" , M98088_REG_35_LVL_MIC1, 0, 31, 1), |
466 | SOC_SINGLE("MIC2 Volume" , M98088_REG_36_LVL_MIC2, 0, 31, 1), |
467 | |
468 | SOC_SINGLE_EXT_TLV("MIC1 Boost Volume" , |
469 | M98088_REG_35_LVL_MIC1, 5, 2, 0, |
470 | max98088_mic1pre_get, max98088_mic1pre_set, |
471 | max98088_micboost_tlv), |
472 | SOC_SINGLE_EXT_TLV("MIC2 Boost Volume" , |
473 | M98088_REG_36_LVL_MIC2, 5, 2, 0, |
474 | max98088_mic2pre_get, max98088_mic2pre_set, |
475 | max98088_micboost_tlv), |
476 | |
477 | SOC_SINGLE("Noise Gate Threshold" , M98088_REG_40_MICAGC_THRESH, |
478 | 4, 15, 0), |
479 | |
480 | SOC_SINGLE("INA Volume" , M98088_REG_37_LVL_INA, 0, 7, 1), |
481 | SOC_SINGLE("INB Volume" , M98088_REG_38_LVL_INB, 0, 7, 1), |
482 | |
483 | SOC_SINGLE("ADCL Volume" , M98088_REG_33_LVL_ADC_L, 0, 15, 0), |
484 | SOC_SINGLE("ADCR Volume" , M98088_REG_34_LVL_ADC_R, 0, 15, 0), |
485 | |
486 | SOC_SINGLE("ADCL Boost Volume" , M98088_REG_33_LVL_ADC_L, 4, 3, 0), |
487 | SOC_SINGLE("ADCR Boost Volume" , M98088_REG_34_LVL_ADC_R, 4, 3, 0), |
488 | |
489 | SOC_SINGLE("EQ1 Switch" , M98088_REG_49_CFG_LEVEL, 0, 1, 0), |
490 | SOC_SINGLE("EQ2 Switch" , M98088_REG_49_CFG_LEVEL, 1, 1, 0), |
491 | |
492 | SOC_ENUM("EX Limiter Mode" , max98088_exmode_enum), |
493 | SOC_ENUM("EX Limiter Threshold" , max98088_ex_thresh_enum), |
494 | |
495 | SOC_ENUM("DAI1 Filter Mode" , max98088_filter_mode_enum), |
496 | SOC_ENUM("DAI1 DAC Filter" , max98088_dai1_dac_filter_enum), |
497 | SOC_ENUM("DAI1 ADC Filter" , max98088_dai1_adc_filter_enum), |
498 | SOC_SINGLE("DAI2 DC Block Switch" , M98088_REG_20_DAI2_FILTERS, |
499 | 0, 1, 0), |
500 | |
501 | SOC_SINGLE("ALC Switch" , M98088_REG_43_SPKALC_COMP, 7, 1, 0), |
502 | SOC_SINGLE("ALC Threshold" , M98088_REG_43_SPKALC_COMP, 0, 7, 0), |
503 | SOC_SINGLE("ALC Multiband" , M98088_REG_43_SPKALC_COMP, 3, 1, 0), |
504 | SOC_SINGLE("ALC Release Time" , M98088_REG_43_SPKALC_COMP, 4, 7, 0), |
505 | |
506 | SOC_SINGLE("PWR Limiter Threshold" , M98088_REG_44_PWRLMT_CFG, |
507 | 4, 15, 0), |
508 | SOC_SINGLE("PWR Limiter Weight" , M98088_REG_44_PWRLMT_CFG, 0, 7, 0), |
509 | SOC_SINGLE("PWR Limiter Time1" , M98088_REG_45_PWRLMT_TIME, 0, 15, 0), |
510 | SOC_SINGLE("PWR Limiter Time2" , M98088_REG_45_PWRLMT_TIME, 4, 15, 0), |
511 | |
512 | SOC_SINGLE("THD Limiter Threshold" , M98088_REG_46_THDLMT_CFG, 4, 15, 0), |
513 | SOC_SINGLE("THD Limiter Time" , M98088_REG_46_THDLMT_CFG, 0, 7, 0), |
514 | }; |
515 | |
516 | /* Left speaker mixer switch */ |
517 | static const struct snd_kcontrol_new max98088_left_speaker_mixer_controls[] = { |
518 | SOC_DAPM_SINGLE("Left DAC1 Switch" , M98088_REG_2B_MIX_SPK_LEFT, 0, 1, 0), |
519 | SOC_DAPM_SINGLE("Right DAC1 Switch" , M98088_REG_2B_MIX_SPK_LEFT, 7, 1, 0), |
520 | SOC_DAPM_SINGLE("Left DAC2 Switch" , M98088_REG_2B_MIX_SPK_LEFT, 0, 1, 0), |
521 | SOC_DAPM_SINGLE("Right DAC2 Switch" , M98088_REG_2B_MIX_SPK_LEFT, 7, 1, 0), |
522 | SOC_DAPM_SINGLE("MIC1 Switch" , M98088_REG_2B_MIX_SPK_LEFT, 5, 1, 0), |
523 | SOC_DAPM_SINGLE("MIC2 Switch" , M98088_REG_2B_MIX_SPK_LEFT, 6, 1, 0), |
524 | SOC_DAPM_SINGLE("INA1 Switch" , M98088_REG_2B_MIX_SPK_LEFT, 1, 1, 0), |
525 | SOC_DAPM_SINGLE("INA2 Switch" , M98088_REG_2B_MIX_SPK_LEFT, 2, 1, 0), |
526 | SOC_DAPM_SINGLE("INB1 Switch" , M98088_REG_2B_MIX_SPK_LEFT, 3, 1, 0), |
527 | SOC_DAPM_SINGLE("INB2 Switch" , M98088_REG_2B_MIX_SPK_LEFT, 4, 1, 0), |
528 | }; |
529 | |
530 | /* Right speaker mixer switch */ |
531 | static const struct snd_kcontrol_new max98088_right_speaker_mixer_controls[] = { |
532 | SOC_DAPM_SINGLE("Left DAC1 Switch" , M98088_REG_2C_MIX_SPK_RIGHT, 7, 1, 0), |
533 | SOC_DAPM_SINGLE("Right DAC1 Switch" , M98088_REG_2C_MIX_SPK_RIGHT, 0, 1, 0), |
534 | SOC_DAPM_SINGLE("Left DAC2 Switch" , M98088_REG_2C_MIX_SPK_RIGHT, 7, 1, 0), |
535 | SOC_DAPM_SINGLE("Right DAC2 Switch" , M98088_REG_2C_MIX_SPK_RIGHT, 0, 1, 0), |
536 | SOC_DAPM_SINGLE("MIC1 Switch" , M98088_REG_2C_MIX_SPK_RIGHT, 5, 1, 0), |
537 | SOC_DAPM_SINGLE("MIC2 Switch" , M98088_REG_2C_MIX_SPK_RIGHT, 6, 1, 0), |
538 | SOC_DAPM_SINGLE("INA1 Switch" , M98088_REG_2C_MIX_SPK_RIGHT, 1, 1, 0), |
539 | SOC_DAPM_SINGLE("INA2 Switch" , M98088_REG_2C_MIX_SPK_RIGHT, 2, 1, 0), |
540 | SOC_DAPM_SINGLE("INB1 Switch" , M98088_REG_2C_MIX_SPK_RIGHT, 3, 1, 0), |
541 | SOC_DAPM_SINGLE("INB2 Switch" , M98088_REG_2C_MIX_SPK_RIGHT, 4, 1, 0), |
542 | }; |
543 | |
544 | /* Left headphone mixer switch */ |
545 | static const struct snd_kcontrol_new max98088_left_hp_mixer_controls[] = { |
546 | SOC_DAPM_SINGLE("Left DAC1 Switch" , M98088_REG_25_MIX_HP_LEFT, 0, 1, 0), |
547 | SOC_DAPM_SINGLE("Right DAC1 Switch" , M98088_REG_25_MIX_HP_LEFT, 7, 1, 0), |
548 | SOC_DAPM_SINGLE("Left DAC2 Switch" , M98088_REG_25_MIX_HP_LEFT, 0, 1, 0), |
549 | SOC_DAPM_SINGLE("Right DAC2 Switch" , M98088_REG_25_MIX_HP_LEFT, 7, 1, 0), |
550 | SOC_DAPM_SINGLE("MIC1 Switch" , M98088_REG_25_MIX_HP_LEFT, 5, 1, 0), |
551 | SOC_DAPM_SINGLE("MIC2 Switch" , M98088_REG_25_MIX_HP_LEFT, 6, 1, 0), |
552 | SOC_DAPM_SINGLE("INA1 Switch" , M98088_REG_25_MIX_HP_LEFT, 1, 1, 0), |
553 | SOC_DAPM_SINGLE("INA2 Switch" , M98088_REG_25_MIX_HP_LEFT, 2, 1, 0), |
554 | SOC_DAPM_SINGLE("INB1 Switch" , M98088_REG_25_MIX_HP_LEFT, 3, 1, 0), |
555 | SOC_DAPM_SINGLE("INB2 Switch" , M98088_REG_25_MIX_HP_LEFT, 4, 1, 0), |
556 | }; |
557 | |
558 | /* Right headphone mixer switch */ |
559 | static const struct snd_kcontrol_new max98088_right_hp_mixer_controls[] = { |
560 | SOC_DAPM_SINGLE("Left DAC1 Switch" , M98088_REG_26_MIX_HP_RIGHT, 7, 1, 0), |
561 | SOC_DAPM_SINGLE("Right DAC1 Switch" , M98088_REG_26_MIX_HP_RIGHT, 0, 1, 0), |
562 | SOC_DAPM_SINGLE("Left DAC2 Switch" , M98088_REG_26_MIX_HP_RIGHT, 7, 1, 0), |
563 | SOC_DAPM_SINGLE("Right DAC2 Switch" , M98088_REG_26_MIX_HP_RIGHT, 0, 1, 0), |
564 | SOC_DAPM_SINGLE("MIC1 Switch" , M98088_REG_26_MIX_HP_RIGHT, 5, 1, 0), |
565 | SOC_DAPM_SINGLE("MIC2 Switch" , M98088_REG_26_MIX_HP_RIGHT, 6, 1, 0), |
566 | SOC_DAPM_SINGLE("INA1 Switch" , M98088_REG_26_MIX_HP_RIGHT, 1, 1, 0), |
567 | SOC_DAPM_SINGLE("INA2 Switch" , M98088_REG_26_MIX_HP_RIGHT, 2, 1, 0), |
568 | SOC_DAPM_SINGLE("INB1 Switch" , M98088_REG_26_MIX_HP_RIGHT, 3, 1, 0), |
569 | SOC_DAPM_SINGLE("INB2 Switch" , M98088_REG_26_MIX_HP_RIGHT, 4, 1, 0), |
570 | }; |
571 | |
572 | /* Left earpiece/receiver mixer switch */ |
573 | static const struct snd_kcontrol_new max98088_left_rec_mixer_controls[] = { |
574 | SOC_DAPM_SINGLE("Left DAC1 Switch" , M98088_REG_28_MIX_REC_LEFT, 0, 1, 0), |
575 | SOC_DAPM_SINGLE("Right DAC1 Switch" , M98088_REG_28_MIX_REC_LEFT, 7, 1, 0), |
576 | SOC_DAPM_SINGLE("Left DAC2 Switch" , M98088_REG_28_MIX_REC_LEFT, 0, 1, 0), |
577 | SOC_DAPM_SINGLE("Right DAC2 Switch" , M98088_REG_28_MIX_REC_LEFT, 7, 1, 0), |
578 | SOC_DAPM_SINGLE("MIC1 Switch" , M98088_REG_28_MIX_REC_LEFT, 5, 1, 0), |
579 | SOC_DAPM_SINGLE("MIC2 Switch" , M98088_REG_28_MIX_REC_LEFT, 6, 1, 0), |
580 | SOC_DAPM_SINGLE("INA1 Switch" , M98088_REG_28_MIX_REC_LEFT, 1, 1, 0), |
581 | SOC_DAPM_SINGLE("INA2 Switch" , M98088_REG_28_MIX_REC_LEFT, 2, 1, 0), |
582 | SOC_DAPM_SINGLE("INB1 Switch" , M98088_REG_28_MIX_REC_LEFT, 3, 1, 0), |
583 | SOC_DAPM_SINGLE("INB2 Switch" , M98088_REG_28_MIX_REC_LEFT, 4, 1, 0), |
584 | }; |
585 | |
586 | /* Right earpiece/receiver mixer switch */ |
587 | static const struct snd_kcontrol_new max98088_right_rec_mixer_controls[] = { |
588 | SOC_DAPM_SINGLE("Left DAC1 Switch" , M98088_REG_29_MIX_REC_RIGHT, 7, 1, 0), |
589 | SOC_DAPM_SINGLE("Right DAC1 Switch" , M98088_REG_29_MIX_REC_RIGHT, 0, 1, 0), |
590 | SOC_DAPM_SINGLE("Left DAC2 Switch" , M98088_REG_29_MIX_REC_RIGHT, 7, 1, 0), |
591 | SOC_DAPM_SINGLE("Right DAC2 Switch" , M98088_REG_29_MIX_REC_RIGHT, 0, 1, 0), |
592 | SOC_DAPM_SINGLE("MIC1 Switch" , M98088_REG_29_MIX_REC_RIGHT, 5, 1, 0), |
593 | SOC_DAPM_SINGLE("MIC2 Switch" , M98088_REG_29_MIX_REC_RIGHT, 6, 1, 0), |
594 | SOC_DAPM_SINGLE("INA1 Switch" , M98088_REG_29_MIX_REC_RIGHT, 1, 1, 0), |
595 | SOC_DAPM_SINGLE("INA2 Switch" , M98088_REG_29_MIX_REC_RIGHT, 2, 1, 0), |
596 | SOC_DAPM_SINGLE("INB1 Switch" , M98088_REG_29_MIX_REC_RIGHT, 3, 1, 0), |
597 | SOC_DAPM_SINGLE("INB2 Switch" , M98088_REG_29_MIX_REC_RIGHT, 4, 1, 0), |
598 | }; |
599 | |
600 | /* Left ADC mixer switch */ |
601 | static const struct snd_kcontrol_new max98088_left_ADC_mixer_controls[] = { |
602 | SOC_DAPM_SINGLE("MIC1 Switch" , M98088_REG_23_MIX_ADC_LEFT, 7, 1, 0), |
603 | SOC_DAPM_SINGLE("MIC2 Switch" , M98088_REG_23_MIX_ADC_LEFT, 6, 1, 0), |
604 | SOC_DAPM_SINGLE("INA1 Switch" , M98088_REG_23_MIX_ADC_LEFT, 3, 1, 0), |
605 | SOC_DAPM_SINGLE("INA2 Switch" , M98088_REG_23_MIX_ADC_LEFT, 2, 1, 0), |
606 | SOC_DAPM_SINGLE("INB1 Switch" , M98088_REG_23_MIX_ADC_LEFT, 1, 1, 0), |
607 | SOC_DAPM_SINGLE("INB2 Switch" , M98088_REG_23_MIX_ADC_LEFT, 0, 1, 0), |
608 | }; |
609 | |
610 | /* Right ADC mixer switch */ |
611 | static const struct snd_kcontrol_new max98088_right_ADC_mixer_controls[] = { |
612 | SOC_DAPM_SINGLE("MIC1 Switch" , M98088_REG_24_MIX_ADC_RIGHT, 7, 1, 0), |
613 | SOC_DAPM_SINGLE("MIC2 Switch" , M98088_REG_24_MIX_ADC_RIGHT, 6, 1, 0), |
614 | SOC_DAPM_SINGLE("INA1 Switch" , M98088_REG_24_MIX_ADC_RIGHT, 3, 1, 0), |
615 | SOC_DAPM_SINGLE("INA2 Switch" , M98088_REG_24_MIX_ADC_RIGHT, 2, 1, 0), |
616 | SOC_DAPM_SINGLE("INB1 Switch" , M98088_REG_24_MIX_ADC_RIGHT, 1, 1, 0), |
617 | SOC_DAPM_SINGLE("INB2 Switch" , M98088_REG_24_MIX_ADC_RIGHT, 0, 1, 0), |
618 | }; |
619 | |
620 | static int max98088_mic_event(struct snd_soc_dapm_widget *w, |
621 | struct snd_kcontrol *kcontrol, int event) |
622 | { |
623 | struct snd_soc_component *component = snd_soc_dapm_to_component(dapm: w->dapm); |
624 | struct max98088_priv *max98088 = snd_soc_component_get_drvdata(c: component); |
625 | |
626 | switch (event) { |
627 | case SND_SOC_DAPM_POST_PMU: |
628 | if (w->reg == M98088_REG_35_LVL_MIC1) { |
629 | snd_soc_component_update_bits(component, reg: w->reg, M98088_MICPRE_MASK, |
630 | val: (1+max98088->mic1pre)<<M98088_MICPRE_SHIFT); |
631 | } else { |
632 | snd_soc_component_update_bits(component, reg: w->reg, M98088_MICPRE_MASK, |
633 | val: (1+max98088->mic2pre)<<M98088_MICPRE_SHIFT); |
634 | } |
635 | break; |
636 | case SND_SOC_DAPM_POST_PMD: |
637 | snd_soc_component_update_bits(component, reg: w->reg, M98088_MICPRE_MASK, val: 0); |
638 | break; |
639 | default: |
640 | return -EINVAL; |
641 | } |
642 | |
643 | return 0; |
644 | } |
645 | |
646 | /* |
647 | * The line inputs are 2-channel stereo inputs with the left |
648 | * and right channels sharing a common PGA power control signal. |
649 | */ |
650 | static int max98088_line_pga(struct snd_soc_dapm_widget *w, |
651 | int event, int line, u8 channel) |
652 | { |
653 | struct snd_soc_component *component = snd_soc_dapm_to_component(dapm: w->dapm); |
654 | struct max98088_priv *max98088 = snd_soc_component_get_drvdata(c: component); |
655 | u8 *state; |
656 | |
657 | if (WARN_ON(!(channel == 1 || channel == 2))) |
658 | return -EINVAL; |
659 | |
660 | switch (line) { |
661 | case LINE_INA: |
662 | state = &max98088->ina_state; |
663 | break; |
664 | case LINE_INB: |
665 | state = &max98088->inb_state; |
666 | break; |
667 | default: |
668 | return -EINVAL; |
669 | } |
670 | |
671 | switch (event) { |
672 | case SND_SOC_DAPM_POST_PMU: |
673 | *state |= channel; |
674 | snd_soc_component_update_bits(component, reg: w->reg, |
675 | mask: (1 << w->shift), val: (1 << w->shift)); |
676 | break; |
677 | case SND_SOC_DAPM_POST_PMD: |
678 | *state &= ~channel; |
679 | if (*state == 0) { |
680 | snd_soc_component_update_bits(component, reg: w->reg, |
681 | mask: (1 << w->shift), val: 0); |
682 | } |
683 | break; |
684 | default: |
685 | return -EINVAL; |
686 | } |
687 | |
688 | return 0; |
689 | } |
690 | |
691 | static int max98088_pga_ina1_event(struct snd_soc_dapm_widget *w, |
692 | struct snd_kcontrol *k, int event) |
693 | { |
694 | return max98088_line_pga(w, event, LINE_INA, channel: 1); |
695 | } |
696 | |
697 | static int max98088_pga_ina2_event(struct snd_soc_dapm_widget *w, |
698 | struct snd_kcontrol *k, int event) |
699 | { |
700 | return max98088_line_pga(w, event, LINE_INA, channel: 2); |
701 | } |
702 | |
703 | static int max98088_pga_inb1_event(struct snd_soc_dapm_widget *w, |
704 | struct snd_kcontrol *k, int event) |
705 | { |
706 | return max98088_line_pga(w, event, LINE_INB, channel: 1); |
707 | } |
708 | |
709 | static int max98088_pga_inb2_event(struct snd_soc_dapm_widget *w, |
710 | struct snd_kcontrol *k, int event) |
711 | { |
712 | return max98088_line_pga(w, event, LINE_INB, channel: 2); |
713 | } |
714 | |
715 | static const struct snd_soc_dapm_widget max98088_dapm_widgets[] = { |
716 | |
717 | SND_SOC_DAPM_ADC("ADCL" , "HiFi Capture" , M98088_REG_4C_PWR_EN_IN, 1, 0), |
718 | SND_SOC_DAPM_ADC("ADCR" , "HiFi Capture" , M98088_REG_4C_PWR_EN_IN, 0, 0), |
719 | |
720 | SND_SOC_DAPM_DAC("DACL1" , "HiFi Playback" , |
721 | M98088_REG_4D_PWR_EN_OUT, 1, 0), |
722 | SND_SOC_DAPM_DAC("DACR1" , "HiFi Playback" , |
723 | M98088_REG_4D_PWR_EN_OUT, 0, 0), |
724 | SND_SOC_DAPM_DAC("DACL2" , "Aux Playback" , |
725 | M98088_REG_4D_PWR_EN_OUT, 1, 0), |
726 | SND_SOC_DAPM_DAC("DACR2" , "Aux Playback" , |
727 | M98088_REG_4D_PWR_EN_OUT, 0, 0), |
728 | |
729 | SND_SOC_DAPM_PGA("HP Left Out" , M98088_REG_4D_PWR_EN_OUT, |
730 | 7, 0, NULL, 0), |
731 | SND_SOC_DAPM_PGA("HP Right Out" , M98088_REG_4D_PWR_EN_OUT, |
732 | 6, 0, NULL, 0), |
733 | |
734 | SND_SOC_DAPM_PGA("SPK Left Out" , M98088_REG_4D_PWR_EN_OUT, |
735 | 5, 0, NULL, 0), |
736 | SND_SOC_DAPM_PGA("SPK Right Out" , M98088_REG_4D_PWR_EN_OUT, |
737 | 4, 0, NULL, 0), |
738 | |
739 | SND_SOC_DAPM_PGA("REC Left Out" , M98088_REG_4D_PWR_EN_OUT, |
740 | 3, 0, NULL, 0), |
741 | SND_SOC_DAPM_PGA("REC Right Out" , M98088_REG_4D_PWR_EN_OUT, |
742 | 2, 0, NULL, 0), |
743 | |
744 | SND_SOC_DAPM_MUX("External MIC" , SND_SOC_NOPM, 0, 0, |
745 | &max98088_extmic_mux), |
746 | |
747 | SND_SOC_DAPM_MIXER("Left HP Mixer" , SND_SOC_NOPM, 0, 0, |
748 | &max98088_left_hp_mixer_controls[0], |
749 | ARRAY_SIZE(max98088_left_hp_mixer_controls)), |
750 | |
751 | SND_SOC_DAPM_MIXER("Right HP Mixer" , SND_SOC_NOPM, 0, 0, |
752 | &max98088_right_hp_mixer_controls[0], |
753 | ARRAY_SIZE(max98088_right_hp_mixer_controls)), |
754 | |
755 | SND_SOC_DAPM_MIXER("Left SPK Mixer" , SND_SOC_NOPM, 0, 0, |
756 | &max98088_left_speaker_mixer_controls[0], |
757 | ARRAY_SIZE(max98088_left_speaker_mixer_controls)), |
758 | |
759 | SND_SOC_DAPM_MIXER("Right SPK Mixer" , SND_SOC_NOPM, 0, 0, |
760 | &max98088_right_speaker_mixer_controls[0], |
761 | ARRAY_SIZE(max98088_right_speaker_mixer_controls)), |
762 | |
763 | SND_SOC_DAPM_MIXER("Left REC Mixer" , SND_SOC_NOPM, 0, 0, |
764 | &max98088_left_rec_mixer_controls[0], |
765 | ARRAY_SIZE(max98088_left_rec_mixer_controls)), |
766 | |
767 | SND_SOC_DAPM_MIXER("Right REC Mixer" , SND_SOC_NOPM, 0, 0, |
768 | &max98088_right_rec_mixer_controls[0], |
769 | ARRAY_SIZE(max98088_right_rec_mixer_controls)), |
770 | |
771 | SND_SOC_DAPM_MIXER("Left ADC Mixer" , SND_SOC_NOPM, 0, 0, |
772 | &max98088_left_ADC_mixer_controls[0], |
773 | ARRAY_SIZE(max98088_left_ADC_mixer_controls)), |
774 | |
775 | SND_SOC_DAPM_MIXER("Right ADC Mixer" , SND_SOC_NOPM, 0, 0, |
776 | &max98088_right_ADC_mixer_controls[0], |
777 | ARRAY_SIZE(max98088_right_ADC_mixer_controls)), |
778 | |
779 | SND_SOC_DAPM_PGA_E("MIC1 Input" , M98088_REG_35_LVL_MIC1, |
780 | 5, 0, NULL, 0, max98088_mic_event, |
781 | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), |
782 | |
783 | SND_SOC_DAPM_PGA_E("MIC2 Input" , M98088_REG_36_LVL_MIC2, |
784 | 5, 0, NULL, 0, max98088_mic_event, |
785 | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), |
786 | |
787 | SND_SOC_DAPM_PGA_E("INA1 Input" , M98088_REG_4C_PWR_EN_IN, |
788 | 7, 0, NULL, 0, max98088_pga_ina1_event, |
789 | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), |
790 | |
791 | SND_SOC_DAPM_PGA_E("INA2 Input" , M98088_REG_4C_PWR_EN_IN, |
792 | 7, 0, NULL, 0, max98088_pga_ina2_event, |
793 | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), |
794 | |
795 | SND_SOC_DAPM_PGA_E("INB1 Input" , M98088_REG_4C_PWR_EN_IN, |
796 | 6, 0, NULL, 0, max98088_pga_inb1_event, |
797 | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), |
798 | |
799 | SND_SOC_DAPM_PGA_E("INB2 Input" , M98088_REG_4C_PWR_EN_IN, |
800 | 6, 0, NULL, 0, max98088_pga_inb2_event, |
801 | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), |
802 | |
803 | SND_SOC_DAPM_MICBIAS("MICBIAS" , M98088_REG_4C_PWR_EN_IN, 3, 0), |
804 | |
805 | SND_SOC_DAPM_OUTPUT("HPL" ), |
806 | SND_SOC_DAPM_OUTPUT("HPR" ), |
807 | SND_SOC_DAPM_OUTPUT("SPKL" ), |
808 | SND_SOC_DAPM_OUTPUT("SPKR" ), |
809 | SND_SOC_DAPM_OUTPUT("RECL" ), |
810 | SND_SOC_DAPM_OUTPUT("RECR" ), |
811 | |
812 | SND_SOC_DAPM_INPUT("MIC1" ), |
813 | SND_SOC_DAPM_INPUT("MIC2" ), |
814 | SND_SOC_DAPM_INPUT("INA1" ), |
815 | SND_SOC_DAPM_INPUT("INA2" ), |
816 | SND_SOC_DAPM_INPUT("INB1" ), |
817 | SND_SOC_DAPM_INPUT("INB2" ), |
818 | }; |
819 | |
820 | static const struct snd_soc_dapm_route max98088_audio_map[] = { |
821 | /* Left headphone output mixer */ |
822 | {"Left HP Mixer" , "Left DAC1 Switch" , "DACL1" }, |
823 | {"Left HP Mixer" , "Left DAC2 Switch" , "DACL2" }, |
824 | {"Left HP Mixer" , "Right DAC1 Switch" , "DACR1" }, |
825 | {"Left HP Mixer" , "Right DAC2 Switch" , "DACR2" }, |
826 | {"Left HP Mixer" , "MIC1 Switch" , "MIC1 Input" }, |
827 | {"Left HP Mixer" , "MIC2 Switch" , "MIC2 Input" }, |
828 | {"Left HP Mixer" , "INA1 Switch" , "INA1 Input" }, |
829 | {"Left HP Mixer" , "INA2 Switch" , "INA2 Input" }, |
830 | {"Left HP Mixer" , "INB1 Switch" , "INB1 Input" }, |
831 | {"Left HP Mixer" , "INB2 Switch" , "INB2 Input" }, |
832 | |
833 | /* Right headphone output mixer */ |
834 | {"Right HP Mixer" , "Left DAC1 Switch" , "DACL1" }, |
835 | {"Right HP Mixer" , "Left DAC2 Switch" , "DACL2" }, |
836 | {"Right HP Mixer" , "Right DAC1 Switch" , "DACR1" }, |
837 | {"Right HP Mixer" , "Right DAC2 Switch" , "DACR2" }, |
838 | {"Right HP Mixer" , "MIC1 Switch" , "MIC1 Input" }, |
839 | {"Right HP Mixer" , "MIC2 Switch" , "MIC2 Input" }, |
840 | {"Right HP Mixer" , "INA1 Switch" , "INA1 Input" }, |
841 | {"Right HP Mixer" , "INA2 Switch" , "INA2 Input" }, |
842 | {"Right HP Mixer" , "INB1 Switch" , "INB1 Input" }, |
843 | {"Right HP Mixer" , "INB2 Switch" , "INB2 Input" }, |
844 | |
845 | /* Left speaker output mixer */ |
846 | {"Left SPK Mixer" , "Left DAC1 Switch" , "DACL1" }, |
847 | {"Left SPK Mixer" , "Left DAC2 Switch" , "DACL2" }, |
848 | {"Left SPK Mixer" , "Right DAC1 Switch" , "DACR1" }, |
849 | {"Left SPK Mixer" , "Right DAC2 Switch" , "DACR2" }, |
850 | {"Left SPK Mixer" , "MIC1 Switch" , "MIC1 Input" }, |
851 | {"Left SPK Mixer" , "MIC2 Switch" , "MIC2 Input" }, |
852 | {"Left SPK Mixer" , "INA1 Switch" , "INA1 Input" }, |
853 | {"Left SPK Mixer" , "INA2 Switch" , "INA2 Input" }, |
854 | {"Left SPK Mixer" , "INB1 Switch" , "INB1 Input" }, |
855 | {"Left SPK Mixer" , "INB2 Switch" , "INB2 Input" }, |
856 | |
857 | /* Right speaker output mixer */ |
858 | {"Right SPK Mixer" , "Left DAC1 Switch" , "DACL1" }, |
859 | {"Right SPK Mixer" , "Left DAC2 Switch" , "DACL2" }, |
860 | {"Right SPK Mixer" , "Right DAC1 Switch" , "DACR1" }, |
861 | {"Right SPK Mixer" , "Right DAC2 Switch" , "DACR2" }, |
862 | {"Right SPK Mixer" , "MIC1 Switch" , "MIC1 Input" }, |
863 | {"Right SPK Mixer" , "MIC2 Switch" , "MIC2 Input" }, |
864 | {"Right SPK Mixer" , "INA1 Switch" , "INA1 Input" }, |
865 | {"Right SPK Mixer" , "INA2 Switch" , "INA2 Input" }, |
866 | {"Right SPK Mixer" , "INB1 Switch" , "INB1 Input" }, |
867 | {"Right SPK Mixer" , "INB2 Switch" , "INB2 Input" }, |
868 | |
869 | /* Earpiece/Receiver output mixer */ |
870 | {"Left REC Mixer" , "Left DAC1 Switch" , "DACL1" }, |
871 | {"Left REC Mixer" , "Left DAC2 Switch" , "DACL2" }, |
872 | {"Left REC Mixer" , "Right DAC1 Switch" , "DACR1" }, |
873 | {"Left REC Mixer" , "Right DAC2 Switch" , "DACR2" }, |
874 | {"Left REC Mixer" , "MIC1 Switch" , "MIC1 Input" }, |
875 | {"Left REC Mixer" , "MIC2 Switch" , "MIC2 Input" }, |
876 | {"Left REC Mixer" , "INA1 Switch" , "INA1 Input" }, |
877 | {"Left REC Mixer" , "INA2 Switch" , "INA2 Input" }, |
878 | {"Left REC Mixer" , "INB1 Switch" , "INB1 Input" }, |
879 | {"Left REC Mixer" , "INB2 Switch" , "INB2 Input" }, |
880 | |
881 | /* Earpiece/Receiver output mixer */ |
882 | {"Right REC Mixer" , "Left DAC1 Switch" , "DACL1" }, |
883 | {"Right REC Mixer" , "Left DAC2 Switch" , "DACL2" }, |
884 | {"Right REC Mixer" , "Right DAC1 Switch" , "DACR1" }, |
885 | {"Right REC Mixer" , "Right DAC2 Switch" , "DACR2" }, |
886 | {"Right REC Mixer" , "MIC1 Switch" , "MIC1 Input" }, |
887 | {"Right REC Mixer" , "MIC2 Switch" , "MIC2 Input" }, |
888 | {"Right REC Mixer" , "INA1 Switch" , "INA1 Input" }, |
889 | {"Right REC Mixer" , "INA2 Switch" , "INA2 Input" }, |
890 | {"Right REC Mixer" , "INB1 Switch" , "INB1 Input" }, |
891 | {"Right REC Mixer" , "INB2 Switch" , "INB2 Input" }, |
892 | |
893 | {"HP Left Out" , NULL, "Left HP Mixer" }, |
894 | {"HP Right Out" , NULL, "Right HP Mixer" }, |
895 | {"SPK Left Out" , NULL, "Left SPK Mixer" }, |
896 | {"SPK Right Out" , NULL, "Right SPK Mixer" }, |
897 | {"REC Left Out" , NULL, "Left REC Mixer" }, |
898 | {"REC Right Out" , NULL, "Right REC Mixer" }, |
899 | |
900 | {"HPL" , NULL, "HP Left Out" }, |
901 | {"HPR" , NULL, "HP Right Out" }, |
902 | {"SPKL" , NULL, "SPK Left Out" }, |
903 | {"SPKR" , NULL, "SPK Right Out" }, |
904 | {"RECL" , NULL, "REC Left Out" }, |
905 | {"RECR" , NULL, "REC Right Out" }, |
906 | |
907 | /* Left ADC input mixer */ |
908 | {"Left ADC Mixer" , "MIC1 Switch" , "MIC1 Input" }, |
909 | {"Left ADC Mixer" , "MIC2 Switch" , "MIC2 Input" }, |
910 | {"Left ADC Mixer" , "INA1 Switch" , "INA1 Input" }, |
911 | {"Left ADC Mixer" , "INA2 Switch" , "INA2 Input" }, |
912 | {"Left ADC Mixer" , "INB1 Switch" , "INB1 Input" }, |
913 | {"Left ADC Mixer" , "INB2 Switch" , "INB2 Input" }, |
914 | |
915 | /* Right ADC input mixer */ |
916 | {"Right ADC Mixer" , "MIC1 Switch" , "MIC1 Input" }, |
917 | {"Right ADC Mixer" , "MIC2 Switch" , "MIC2 Input" }, |
918 | {"Right ADC Mixer" , "INA1 Switch" , "INA1 Input" }, |
919 | {"Right ADC Mixer" , "INA2 Switch" , "INA2 Input" }, |
920 | {"Right ADC Mixer" , "INB1 Switch" , "INB1 Input" }, |
921 | {"Right ADC Mixer" , "INB2 Switch" , "INB2 Input" }, |
922 | |
923 | /* Inputs */ |
924 | {"ADCL" , NULL, "Left ADC Mixer" }, |
925 | {"ADCR" , NULL, "Right ADC Mixer" }, |
926 | {"INA1 Input" , NULL, "INA1" }, |
927 | {"INA2 Input" , NULL, "INA2" }, |
928 | {"INB1 Input" , NULL, "INB1" }, |
929 | {"INB2 Input" , NULL, "INB2" }, |
930 | {"MIC1 Input" , NULL, "MIC1" }, |
931 | {"MIC2 Input" , NULL, "MIC2" }, |
932 | }; |
933 | |
934 | /* codec mclk clock divider coefficients */ |
935 | static const struct { |
936 | u32 rate; |
937 | u8 sr; |
938 | } rate_table[] = { |
939 | {8000, 0x10}, |
940 | {11025, 0x20}, |
941 | {16000, 0x30}, |
942 | {22050, 0x40}, |
943 | {24000, 0x50}, |
944 | {32000, 0x60}, |
945 | {44100, 0x70}, |
946 | {48000, 0x80}, |
947 | {88200, 0x90}, |
948 | {96000, 0xA0}, |
949 | }; |
950 | |
951 | static inline int rate_value(int rate, u8 *value) |
952 | { |
953 | int i; |
954 | |
955 | for (i = 0; i < ARRAY_SIZE(rate_table); i++) { |
956 | if (rate_table[i].rate >= rate) { |
957 | *value = rate_table[i].sr; |
958 | return 0; |
959 | } |
960 | } |
961 | *value = rate_table[0].sr; |
962 | return -EINVAL; |
963 | } |
964 | |
965 | static int max98088_dai1_hw_params(struct snd_pcm_substream *substream, |
966 | struct snd_pcm_hw_params *params, |
967 | struct snd_soc_dai *dai) |
968 | { |
969 | struct snd_soc_component *component = dai->component; |
970 | struct max98088_priv *max98088 = snd_soc_component_get_drvdata(c: component); |
971 | struct max98088_cdata *cdata; |
972 | unsigned long long ni; |
973 | unsigned int rate; |
974 | u8 regval; |
975 | |
976 | cdata = &max98088->dai[0]; |
977 | |
978 | rate = params_rate(p: params); |
979 | |
980 | switch (params_width(p: params)) { |
981 | case 16: |
982 | snd_soc_component_update_bits(component, M98088_REG_14_DAI1_FORMAT, |
983 | M98088_DAI_WS, val: 0); |
984 | break; |
985 | case 24: |
986 | snd_soc_component_update_bits(component, M98088_REG_14_DAI1_FORMAT, |
987 | M98088_DAI_WS, M98088_DAI_WS); |
988 | break; |
989 | default: |
990 | return -EINVAL; |
991 | } |
992 | |
993 | snd_soc_component_update_bits(component, M98088_REG_51_PWR_SYS, M98088_SHDNRUN, val: 0); |
994 | |
995 | if (rate_value(rate, value: ®val)) |
996 | return -EINVAL; |
997 | |
998 | snd_soc_component_update_bits(component, M98088_REG_11_DAI1_CLKMODE, |
999 | M98088_CLKMODE_MASK, val: regval); |
1000 | cdata->rate = rate; |
1001 | |
1002 | /* Configure NI when operating as master */ |
1003 | if (snd_soc_component_read(component, M98088_REG_14_DAI1_FORMAT) |
1004 | & M98088_DAI_MAS) { |
1005 | unsigned long pclk; |
1006 | |
1007 | if (max98088->sysclk == 0) { |
1008 | dev_err(component->dev, "Invalid system clock frequency\n" ); |
1009 | return -EINVAL; |
1010 | } |
1011 | ni = 65536ULL * (rate < 50000 ? 96ULL : 48ULL) |
1012 | * (unsigned long long int)rate; |
1013 | pclk = DIV_ROUND_CLOSEST(max98088->sysclk, max98088->mclk_prescaler); |
1014 | ni = DIV_ROUND_CLOSEST_ULL(ni, pclk); |
1015 | snd_soc_component_write(component, M98088_REG_12_DAI1_CLKCFG_HI, |
1016 | val: (ni >> 8) & 0x7F); |
1017 | snd_soc_component_write(component, M98088_REG_13_DAI1_CLKCFG_LO, |
1018 | val: ni & 0xFF); |
1019 | } |
1020 | |
1021 | /* Update sample rate mode */ |
1022 | if (rate < 50000) |
1023 | snd_soc_component_update_bits(component, M98088_REG_18_DAI1_FILTERS, |
1024 | M98088_DAI_DHF, val: 0); |
1025 | else |
1026 | snd_soc_component_update_bits(component, M98088_REG_18_DAI1_FILTERS, |
1027 | M98088_DAI_DHF, M98088_DAI_DHF); |
1028 | |
1029 | snd_soc_component_update_bits(component, M98088_REG_51_PWR_SYS, M98088_SHDNRUN, |
1030 | M98088_SHDNRUN); |
1031 | |
1032 | return 0; |
1033 | } |
1034 | |
1035 | static int max98088_dai2_hw_params(struct snd_pcm_substream *substream, |
1036 | struct snd_pcm_hw_params *params, |
1037 | struct snd_soc_dai *dai) |
1038 | { |
1039 | struct snd_soc_component *component = dai->component; |
1040 | struct max98088_priv *max98088 = snd_soc_component_get_drvdata(c: component); |
1041 | struct max98088_cdata *cdata; |
1042 | unsigned long long ni; |
1043 | unsigned int rate; |
1044 | u8 regval; |
1045 | |
1046 | cdata = &max98088->dai[1]; |
1047 | |
1048 | rate = params_rate(p: params); |
1049 | |
1050 | switch (params_width(p: params)) { |
1051 | case 16: |
1052 | snd_soc_component_update_bits(component, M98088_REG_1C_DAI2_FORMAT, |
1053 | M98088_DAI_WS, val: 0); |
1054 | break; |
1055 | case 24: |
1056 | snd_soc_component_update_bits(component, M98088_REG_1C_DAI2_FORMAT, |
1057 | M98088_DAI_WS, M98088_DAI_WS); |
1058 | break; |
1059 | default: |
1060 | return -EINVAL; |
1061 | } |
1062 | |
1063 | snd_soc_component_update_bits(component, M98088_REG_51_PWR_SYS, M98088_SHDNRUN, val: 0); |
1064 | |
1065 | if (rate_value(rate, value: ®val)) |
1066 | return -EINVAL; |
1067 | |
1068 | snd_soc_component_update_bits(component, M98088_REG_19_DAI2_CLKMODE, |
1069 | M98088_CLKMODE_MASK, val: regval); |
1070 | cdata->rate = rate; |
1071 | |
1072 | /* Configure NI when operating as master */ |
1073 | if (snd_soc_component_read(component, M98088_REG_1C_DAI2_FORMAT) |
1074 | & M98088_DAI_MAS) { |
1075 | unsigned long pclk; |
1076 | |
1077 | if (max98088->sysclk == 0) { |
1078 | dev_err(component->dev, "Invalid system clock frequency\n" ); |
1079 | return -EINVAL; |
1080 | } |
1081 | ni = 65536ULL * (rate < 50000 ? 96ULL : 48ULL) |
1082 | * (unsigned long long int)rate; |
1083 | pclk = DIV_ROUND_CLOSEST(max98088->sysclk, max98088->mclk_prescaler); |
1084 | ni = DIV_ROUND_CLOSEST_ULL(ni, pclk); |
1085 | snd_soc_component_write(component, M98088_REG_1A_DAI2_CLKCFG_HI, |
1086 | val: (ni >> 8) & 0x7F); |
1087 | snd_soc_component_write(component, M98088_REG_1B_DAI2_CLKCFG_LO, |
1088 | val: ni & 0xFF); |
1089 | } |
1090 | |
1091 | /* Update sample rate mode */ |
1092 | if (rate < 50000) |
1093 | snd_soc_component_update_bits(component, M98088_REG_20_DAI2_FILTERS, |
1094 | M98088_DAI_DHF, val: 0); |
1095 | else |
1096 | snd_soc_component_update_bits(component, M98088_REG_20_DAI2_FILTERS, |
1097 | M98088_DAI_DHF, M98088_DAI_DHF); |
1098 | |
1099 | snd_soc_component_update_bits(component, M98088_REG_51_PWR_SYS, M98088_SHDNRUN, |
1100 | M98088_SHDNRUN); |
1101 | |
1102 | return 0; |
1103 | } |
1104 | |
1105 | static int max98088_dai_set_sysclk(struct snd_soc_dai *dai, |
1106 | int clk_id, unsigned int freq, int dir) |
1107 | { |
1108 | struct snd_soc_component *component = dai->component; |
1109 | struct max98088_priv *max98088 = snd_soc_component_get_drvdata(c: component); |
1110 | |
1111 | /* Requested clock frequency is already setup */ |
1112 | if (freq == max98088->sysclk) |
1113 | return 0; |
1114 | |
1115 | if (!IS_ERR(ptr: max98088->mclk)) { |
1116 | freq = clk_round_rate(clk: max98088->mclk, rate: freq); |
1117 | clk_set_rate(clk: max98088->mclk, rate: freq); |
1118 | } |
1119 | |
1120 | /* Setup clocks for slave mode, and using the PLL |
1121 | * PSCLK = 0x01 (when master clk is 10MHz to 20MHz) |
1122 | * 0x02 (when master clk is 20MHz to 30MHz).. |
1123 | */ |
1124 | if ((freq >= 10000000) && (freq < 20000000)) { |
1125 | snd_soc_component_write(component, M98088_REG_10_SYS_CLK, val: 0x10); |
1126 | max98088->mclk_prescaler = 1; |
1127 | } else if ((freq >= 20000000) && (freq < 30000000)) { |
1128 | snd_soc_component_write(component, M98088_REG_10_SYS_CLK, val: 0x20); |
1129 | max98088->mclk_prescaler = 2; |
1130 | } else { |
1131 | dev_err(component->dev, "Invalid master clock frequency\n" ); |
1132 | return -EINVAL; |
1133 | } |
1134 | |
1135 | if (snd_soc_component_read(component, M98088_REG_51_PWR_SYS) & M98088_SHDNRUN) { |
1136 | snd_soc_component_update_bits(component, M98088_REG_51_PWR_SYS, |
1137 | M98088_SHDNRUN, val: 0); |
1138 | snd_soc_component_update_bits(component, M98088_REG_51_PWR_SYS, |
1139 | M98088_SHDNRUN, M98088_SHDNRUN); |
1140 | } |
1141 | |
1142 | dev_dbg(dai->dev, "Clock source is %d at %uHz\n" , clk_id, freq); |
1143 | |
1144 | max98088->sysclk = freq; |
1145 | return 0; |
1146 | } |
1147 | |
1148 | static int max98088_dai1_set_fmt(struct snd_soc_dai *codec_dai, |
1149 | unsigned int fmt) |
1150 | { |
1151 | struct snd_soc_component *component = codec_dai->component; |
1152 | struct max98088_priv *max98088 = snd_soc_component_get_drvdata(c: component); |
1153 | struct max98088_cdata *cdata; |
1154 | u8 reg15val; |
1155 | u8 reg14val = 0; |
1156 | |
1157 | cdata = &max98088->dai[0]; |
1158 | |
1159 | if (fmt != cdata->fmt) { |
1160 | cdata->fmt = fmt; |
1161 | |
1162 | switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) { |
1163 | case SND_SOC_DAIFMT_CBC_CFC: |
1164 | /* Consumer mode PLL */ |
1165 | snd_soc_component_write(component, M98088_REG_12_DAI1_CLKCFG_HI, |
1166 | val: 0x80); |
1167 | snd_soc_component_write(component, M98088_REG_13_DAI1_CLKCFG_LO, |
1168 | val: 0x00); |
1169 | break; |
1170 | case SND_SOC_DAIFMT_CBP_CFP: |
1171 | /* Set to provider mode */ |
1172 | reg14val |= M98088_DAI_MAS; |
1173 | break; |
1174 | default: |
1175 | dev_err(component->dev, "Clock mode unsupported" ); |
1176 | return -EINVAL; |
1177 | } |
1178 | |
1179 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { |
1180 | case SND_SOC_DAIFMT_I2S: |
1181 | reg14val |= M98088_DAI_DLY; |
1182 | break; |
1183 | case SND_SOC_DAIFMT_LEFT_J: |
1184 | break; |
1185 | default: |
1186 | return -EINVAL; |
1187 | } |
1188 | |
1189 | switch (fmt & SND_SOC_DAIFMT_INV_MASK) { |
1190 | case SND_SOC_DAIFMT_NB_NF: |
1191 | break; |
1192 | case SND_SOC_DAIFMT_NB_IF: |
1193 | reg14val |= M98088_DAI_WCI; |
1194 | break; |
1195 | case SND_SOC_DAIFMT_IB_NF: |
1196 | reg14val |= M98088_DAI_BCI; |
1197 | break; |
1198 | case SND_SOC_DAIFMT_IB_IF: |
1199 | reg14val |= M98088_DAI_BCI|M98088_DAI_WCI; |
1200 | break; |
1201 | default: |
1202 | return -EINVAL; |
1203 | } |
1204 | |
1205 | snd_soc_component_update_bits(component, M98088_REG_14_DAI1_FORMAT, |
1206 | M98088_DAI_MAS | M98088_DAI_DLY | M98088_DAI_BCI | |
1207 | M98088_DAI_WCI, val: reg14val); |
1208 | |
1209 | reg15val = M98088_DAI_BSEL64; |
1210 | if (max98088->digmic) |
1211 | reg15val |= M98088_DAI_OSR64; |
1212 | snd_soc_component_write(component, M98088_REG_15_DAI1_CLOCK, val: reg15val); |
1213 | } |
1214 | |
1215 | return 0; |
1216 | } |
1217 | |
1218 | static int max98088_dai2_set_fmt(struct snd_soc_dai *codec_dai, |
1219 | unsigned int fmt) |
1220 | { |
1221 | struct snd_soc_component *component = codec_dai->component; |
1222 | struct max98088_priv *max98088 = snd_soc_component_get_drvdata(c: component); |
1223 | struct max98088_cdata *cdata; |
1224 | u8 reg1Cval = 0; |
1225 | |
1226 | cdata = &max98088->dai[1]; |
1227 | |
1228 | if (fmt != cdata->fmt) { |
1229 | cdata->fmt = fmt; |
1230 | |
1231 | switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) { |
1232 | case SND_SOC_DAIFMT_CBC_CFC: |
1233 | /* Consumer mode PLL */ |
1234 | snd_soc_component_write(component, M98088_REG_1A_DAI2_CLKCFG_HI, |
1235 | val: 0x80); |
1236 | snd_soc_component_write(component, M98088_REG_1B_DAI2_CLKCFG_LO, |
1237 | val: 0x00); |
1238 | break; |
1239 | case SND_SOC_DAIFMT_CBP_CFP: |
1240 | /* Set to provider mode */ |
1241 | reg1Cval |= M98088_DAI_MAS; |
1242 | break; |
1243 | default: |
1244 | dev_err(component->dev, "Clock mode unsupported" ); |
1245 | return -EINVAL; |
1246 | } |
1247 | |
1248 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { |
1249 | case SND_SOC_DAIFMT_I2S: |
1250 | reg1Cval |= M98088_DAI_DLY; |
1251 | break; |
1252 | case SND_SOC_DAIFMT_LEFT_J: |
1253 | break; |
1254 | default: |
1255 | return -EINVAL; |
1256 | } |
1257 | |
1258 | switch (fmt & SND_SOC_DAIFMT_INV_MASK) { |
1259 | case SND_SOC_DAIFMT_NB_NF: |
1260 | break; |
1261 | case SND_SOC_DAIFMT_NB_IF: |
1262 | reg1Cval |= M98088_DAI_WCI; |
1263 | break; |
1264 | case SND_SOC_DAIFMT_IB_NF: |
1265 | reg1Cval |= M98088_DAI_BCI; |
1266 | break; |
1267 | case SND_SOC_DAIFMT_IB_IF: |
1268 | reg1Cval |= M98088_DAI_BCI|M98088_DAI_WCI; |
1269 | break; |
1270 | default: |
1271 | return -EINVAL; |
1272 | } |
1273 | |
1274 | snd_soc_component_update_bits(component, M98088_REG_1C_DAI2_FORMAT, |
1275 | M98088_DAI_MAS | M98088_DAI_DLY | M98088_DAI_BCI | |
1276 | M98088_DAI_WCI, val: reg1Cval); |
1277 | |
1278 | snd_soc_component_write(component, M98088_REG_1D_DAI2_CLOCK, |
1279 | M98088_DAI_BSEL64); |
1280 | } |
1281 | |
1282 | return 0; |
1283 | } |
1284 | |
1285 | static int max98088_dai1_mute(struct snd_soc_dai *codec_dai, int mute, |
1286 | int direction) |
1287 | { |
1288 | struct snd_soc_component *component = codec_dai->component; |
1289 | int reg; |
1290 | |
1291 | if (mute) |
1292 | reg = M98088_DAI_MUTE; |
1293 | else |
1294 | reg = 0; |
1295 | |
1296 | snd_soc_component_update_bits(component, M98088_REG_2F_LVL_DAI1_PLAY, |
1297 | M98088_DAI_MUTE_MASK, val: reg); |
1298 | return 0; |
1299 | } |
1300 | |
1301 | static int max98088_dai2_mute(struct snd_soc_dai *codec_dai, int mute, |
1302 | int direction) |
1303 | { |
1304 | struct snd_soc_component *component = codec_dai->component; |
1305 | int reg; |
1306 | |
1307 | if (mute) |
1308 | reg = M98088_DAI_MUTE; |
1309 | else |
1310 | reg = 0; |
1311 | |
1312 | snd_soc_component_update_bits(component, M98088_REG_31_LVL_DAI2_PLAY, |
1313 | M98088_DAI_MUTE_MASK, val: reg); |
1314 | return 0; |
1315 | } |
1316 | |
1317 | static int max98088_set_bias_level(struct snd_soc_component *component, |
1318 | enum snd_soc_bias_level level) |
1319 | { |
1320 | struct max98088_priv *max98088 = snd_soc_component_get_drvdata(c: component); |
1321 | |
1322 | switch (level) { |
1323 | case SND_SOC_BIAS_ON: |
1324 | break; |
1325 | |
1326 | case SND_SOC_BIAS_PREPARE: |
1327 | /* |
1328 | * SND_SOC_BIAS_PREPARE is called while preparing for a |
1329 | * transition to ON or away from ON. If current bias_level |
1330 | * is SND_SOC_BIAS_ON, then it is preparing for a transition |
1331 | * away from ON. Disable the clock in that case, otherwise |
1332 | * enable it. |
1333 | */ |
1334 | if (!IS_ERR(ptr: max98088->mclk)) { |
1335 | if (snd_soc_component_get_bias_level(component) == |
1336 | SND_SOC_BIAS_ON) |
1337 | clk_disable_unprepare(clk: max98088->mclk); |
1338 | else |
1339 | clk_prepare_enable(clk: max98088->mclk); |
1340 | } |
1341 | break; |
1342 | |
1343 | case SND_SOC_BIAS_STANDBY: |
1344 | if (snd_soc_component_get_bias_level(component) == SND_SOC_BIAS_OFF) |
1345 | regcache_sync(map: max98088->regmap); |
1346 | |
1347 | snd_soc_component_update_bits(component, M98088_REG_4C_PWR_EN_IN, |
1348 | M98088_MBEN, M98088_MBEN); |
1349 | break; |
1350 | |
1351 | case SND_SOC_BIAS_OFF: |
1352 | snd_soc_component_update_bits(component, M98088_REG_4C_PWR_EN_IN, |
1353 | M98088_MBEN, val: 0); |
1354 | regcache_mark_dirty(map: max98088->regmap); |
1355 | break; |
1356 | } |
1357 | return 0; |
1358 | } |
1359 | |
1360 | #define MAX98088_RATES SNDRV_PCM_RATE_8000_96000 |
1361 | #define MAX98088_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE) |
1362 | |
1363 | static const struct snd_soc_dai_ops max98088_dai1_ops = { |
1364 | .set_sysclk = max98088_dai_set_sysclk, |
1365 | .set_fmt = max98088_dai1_set_fmt, |
1366 | .hw_params = max98088_dai1_hw_params, |
1367 | .mute_stream = max98088_dai1_mute, |
1368 | .no_capture_mute = 1, |
1369 | }; |
1370 | |
1371 | static const struct snd_soc_dai_ops max98088_dai2_ops = { |
1372 | .set_sysclk = max98088_dai_set_sysclk, |
1373 | .set_fmt = max98088_dai2_set_fmt, |
1374 | .hw_params = max98088_dai2_hw_params, |
1375 | .mute_stream = max98088_dai2_mute, |
1376 | .no_capture_mute = 1, |
1377 | }; |
1378 | |
1379 | static struct snd_soc_dai_driver max98088_dai[] = { |
1380 | { |
1381 | .name = "HiFi" , |
1382 | .playback = { |
1383 | .stream_name = "HiFi Playback" , |
1384 | .channels_min = 1, |
1385 | .channels_max = 2, |
1386 | .rates = MAX98088_RATES, |
1387 | .formats = MAX98088_FORMATS, |
1388 | }, |
1389 | .capture = { |
1390 | .stream_name = "HiFi Capture" , |
1391 | .channels_min = 1, |
1392 | .channels_max = 2, |
1393 | .rates = MAX98088_RATES, |
1394 | .formats = MAX98088_FORMATS, |
1395 | }, |
1396 | .ops = &max98088_dai1_ops, |
1397 | }, |
1398 | { |
1399 | .name = "Aux" , |
1400 | .playback = { |
1401 | .stream_name = "Aux Playback" , |
1402 | .channels_min = 1, |
1403 | .channels_max = 2, |
1404 | .rates = MAX98088_RATES, |
1405 | .formats = MAX98088_FORMATS, |
1406 | }, |
1407 | .ops = &max98088_dai2_ops, |
1408 | } |
1409 | }; |
1410 | |
1411 | static const char *eq_mode_name[] = {"EQ1 Mode" , "EQ2 Mode" }; |
1412 | |
1413 | static int max98088_get_channel(struct snd_soc_component *component, const char *name) |
1414 | { |
1415 | int ret; |
1416 | |
1417 | ret = match_string(array: eq_mode_name, ARRAY_SIZE(eq_mode_name), string: name); |
1418 | if (ret < 0) |
1419 | dev_err(component->dev, "Bad EQ channel name '%s'\n" , name); |
1420 | return ret; |
1421 | } |
1422 | |
1423 | static void max98088_setup_eq1(struct snd_soc_component *component) |
1424 | { |
1425 | struct max98088_priv *max98088 = snd_soc_component_get_drvdata(c: component); |
1426 | struct max98088_pdata *pdata = max98088->pdata; |
1427 | struct max98088_eq_cfg *coef_set; |
1428 | int best, best_val, save, i, sel, fs; |
1429 | struct max98088_cdata *cdata; |
1430 | |
1431 | cdata = &max98088->dai[0]; |
1432 | |
1433 | if (!pdata || !max98088->eq_textcnt) |
1434 | return; |
1435 | |
1436 | /* Find the selected configuration with nearest sample rate */ |
1437 | fs = cdata->rate; |
1438 | sel = cdata->eq_sel; |
1439 | |
1440 | best = 0; |
1441 | best_val = INT_MAX; |
1442 | for (i = 0; i < pdata->eq_cfgcnt; i++) { |
1443 | if (strcmp(pdata->eq_cfg[i].name, max98088->eq_texts[sel]) == 0 && |
1444 | abs(pdata->eq_cfg[i].rate - fs) < best_val) { |
1445 | best = i; |
1446 | best_val = abs(pdata->eq_cfg[i].rate - fs); |
1447 | } |
1448 | } |
1449 | |
1450 | dev_dbg(component->dev, "Selected %s/%dHz for %dHz sample rate\n" , |
1451 | pdata->eq_cfg[best].name, |
1452 | pdata->eq_cfg[best].rate, fs); |
1453 | |
1454 | /* Disable EQ while configuring, and save current on/off state */ |
1455 | save = snd_soc_component_read(component, M98088_REG_49_CFG_LEVEL); |
1456 | snd_soc_component_update_bits(component, M98088_REG_49_CFG_LEVEL, M98088_EQ1EN, val: 0); |
1457 | |
1458 | coef_set = &pdata->eq_cfg[sel]; |
1459 | |
1460 | m98088_eq_band(component, dai: 0, band: 0, coefs: coef_set->band1); |
1461 | m98088_eq_band(component, dai: 0, band: 1, coefs: coef_set->band2); |
1462 | m98088_eq_band(component, dai: 0, band: 2, coefs: coef_set->band3); |
1463 | m98088_eq_band(component, dai: 0, band: 3, coefs: coef_set->band4); |
1464 | m98088_eq_band(component, dai: 0, band: 4, coefs: coef_set->band5); |
1465 | |
1466 | /* Restore the original on/off state */ |
1467 | snd_soc_component_update_bits(component, M98088_REG_49_CFG_LEVEL, M98088_EQ1EN, val: save); |
1468 | } |
1469 | |
1470 | static void max98088_setup_eq2(struct snd_soc_component *component) |
1471 | { |
1472 | struct max98088_priv *max98088 = snd_soc_component_get_drvdata(c: component); |
1473 | struct max98088_pdata *pdata = max98088->pdata; |
1474 | struct max98088_eq_cfg *coef_set; |
1475 | int best, best_val, save, i, sel, fs; |
1476 | struct max98088_cdata *cdata; |
1477 | |
1478 | cdata = &max98088->dai[1]; |
1479 | |
1480 | if (!pdata || !max98088->eq_textcnt) |
1481 | return; |
1482 | |
1483 | /* Find the selected configuration with nearest sample rate */ |
1484 | fs = cdata->rate; |
1485 | |
1486 | sel = cdata->eq_sel; |
1487 | best = 0; |
1488 | best_val = INT_MAX; |
1489 | for (i = 0; i < pdata->eq_cfgcnt; i++) { |
1490 | if (strcmp(pdata->eq_cfg[i].name, max98088->eq_texts[sel]) == 0 && |
1491 | abs(pdata->eq_cfg[i].rate - fs) < best_val) { |
1492 | best = i; |
1493 | best_val = abs(pdata->eq_cfg[i].rate - fs); |
1494 | } |
1495 | } |
1496 | |
1497 | dev_dbg(component->dev, "Selected %s/%dHz for %dHz sample rate\n" , |
1498 | pdata->eq_cfg[best].name, |
1499 | pdata->eq_cfg[best].rate, fs); |
1500 | |
1501 | /* Disable EQ while configuring, and save current on/off state */ |
1502 | save = snd_soc_component_read(component, M98088_REG_49_CFG_LEVEL); |
1503 | snd_soc_component_update_bits(component, M98088_REG_49_CFG_LEVEL, M98088_EQ2EN, val: 0); |
1504 | |
1505 | coef_set = &pdata->eq_cfg[sel]; |
1506 | |
1507 | m98088_eq_band(component, dai: 1, band: 0, coefs: coef_set->band1); |
1508 | m98088_eq_band(component, dai: 1, band: 1, coefs: coef_set->band2); |
1509 | m98088_eq_band(component, dai: 1, band: 2, coefs: coef_set->band3); |
1510 | m98088_eq_band(component, dai: 1, band: 3, coefs: coef_set->band4); |
1511 | m98088_eq_band(component, dai: 1, band: 4, coefs: coef_set->band5); |
1512 | |
1513 | /* Restore the original on/off state */ |
1514 | snd_soc_component_update_bits(component, M98088_REG_49_CFG_LEVEL, M98088_EQ2EN, |
1515 | val: save); |
1516 | } |
1517 | |
1518 | static int max98088_put_eq_enum(struct snd_kcontrol *kcontrol, |
1519 | struct snd_ctl_elem_value *ucontrol) |
1520 | { |
1521 | struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); |
1522 | struct max98088_priv *max98088 = snd_soc_component_get_drvdata(c: component); |
1523 | struct max98088_pdata *pdata = max98088->pdata; |
1524 | int channel = max98088_get_channel(component, name: kcontrol->id.name); |
1525 | struct max98088_cdata *cdata; |
1526 | int sel = ucontrol->value.enumerated.item[0]; |
1527 | |
1528 | if (channel < 0) |
1529 | return channel; |
1530 | |
1531 | cdata = &max98088->dai[channel]; |
1532 | |
1533 | if (sel >= pdata->eq_cfgcnt) |
1534 | return -EINVAL; |
1535 | |
1536 | cdata->eq_sel = sel; |
1537 | |
1538 | switch (channel) { |
1539 | case 0: |
1540 | max98088_setup_eq1(component); |
1541 | break; |
1542 | case 1: |
1543 | max98088_setup_eq2(component); |
1544 | break; |
1545 | } |
1546 | |
1547 | return 0; |
1548 | } |
1549 | |
1550 | static int max98088_get_eq_enum(struct snd_kcontrol *kcontrol, |
1551 | struct snd_ctl_elem_value *ucontrol) |
1552 | { |
1553 | struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); |
1554 | struct max98088_priv *max98088 = snd_soc_component_get_drvdata(c: component); |
1555 | int channel = max98088_get_channel(component, name: kcontrol->id.name); |
1556 | struct max98088_cdata *cdata; |
1557 | |
1558 | if (channel < 0) |
1559 | return channel; |
1560 | |
1561 | cdata = &max98088->dai[channel]; |
1562 | ucontrol->value.enumerated.item[0] = cdata->eq_sel; |
1563 | return 0; |
1564 | } |
1565 | |
1566 | static void max98088_handle_eq_pdata(struct snd_soc_component *component) |
1567 | { |
1568 | struct max98088_priv *max98088 = snd_soc_component_get_drvdata(c: component); |
1569 | struct max98088_pdata *pdata = max98088->pdata; |
1570 | struct max98088_eq_cfg *cfg; |
1571 | unsigned int cfgcnt; |
1572 | int i, j; |
1573 | const char **t; |
1574 | int ret; |
1575 | struct snd_kcontrol_new controls[] = { |
1576 | SOC_ENUM_EXT((char *)eq_mode_name[0], |
1577 | max98088->eq_enum, |
1578 | max98088_get_eq_enum, |
1579 | max98088_put_eq_enum), |
1580 | SOC_ENUM_EXT((char *)eq_mode_name[1], |
1581 | max98088->eq_enum, |
1582 | max98088_get_eq_enum, |
1583 | max98088_put_eq_enum), |
1584 | }; |
1585 | BUILD_BUG_ON(ARRAY_SIZE(controls) != ARRAY_SIZE(eq_mode_name)); |
1586 | |
1587 | cfg = pdata->eq_cfg; |
1588 | cfgcnt = pdata->eq_cfgcnt; |
1589 | |
1590 | /* Setup an array of texts for the equalizer enum. |
1591 | * This is based on Mark Brown's equalizer driver code. |
1592 | */ |
1593 | max98088->eq_textcnt = 0; |
1594 | max98088->eq_texts = NULL; |
1595 | for (i = 0; i < cfgcnt; i++) { |
1596 | for (j = 0; j < max98088->eq_textcnt; j++) { |
1597 | if (strcmp(cfg[i].name, max98088->eq_texts[j]) == 0) |
1598 | break; |
1599 | } |
1600 | |
1601 | if (j != max98088->eq_textcnt) |
1602 | continue; |
1603 | |
1604 | /* Expand the array */ |
1605 | t = krealloc(objp: max98088->eq_texts, |
1606 | new_size: sizeof(char *) * (max98088->eq_textcnt + 1), |
1607 | GFP_KERNEL); |
1608 | if (t == NULL) |
1609 | continue; |
1610 | |
1611 | /* Store the new entry */ |
1612 | t[max98088->eq_textcnt] = cfg[i].name; |
1613 | max98088->eq_textcnt++; |
1614 | max98088->eq_texts = t; |
1615 | } |
1616 | |
1617 | /* Now point the soc_enum to .texts array items */ |
1618 | max98088->eq_enum.texts = max98088->eq_texts; |
1619 | max98088->eq_enum.items = max98088->eq_textcnt; |
1620 | |
1621 | ret = snd_soc_add_component_controls(component, controls, ARRAY_SIZE(controls)); |
1622 | if (ret != 0) |
1623 | dev_err(component->dev, "Failed to add EQ control: %d\n" , ret); |
1624 | } |
1625 | |
1626 | static void max98088_handle_pdata(struct snd_soc_component *component) |
1627 | { |
1628 | struct max98088_priv *max98088 = snd_soc_component_get_drvdata(c: component); |
1629 | struct max98088_pdata *pdata = max98088->pdata; |
1630 | u8 regval = 0; |
1631 | |
1632 | if (!pdata) { |
1633 | dev_dbg(component->dev, "No platform data\n" ); |
1634 | return; |
1635 | } |
1636 | |
1637 | /* Configure mic for analog/digital mic mode */ |
1638 | if (pdata->digmic_left_mode) |
1639 | regval |= M98088_DIGMIC_L; |
1640 | |
1641 | if (pdata->digmic_right_mode) |
1642 | regval |= M98088_DIGMIC_R; |
1643 | |
1644 | max98088->digmic = (regval ? 1 : 0); |
1645 | |
1646 | snd_soc_component_write(component, M98088_REG_48_CFG_MIC, val: regval); |
1647 | |
1648 | /* Configure receiver output */ |
1649 | regval = ((pdata->receiver_mode) ? M98088_REC_LINEMODE : 0); |
1650 | snd_soc_component_update_bits(component, M98088_REG_2A_MIC_REC_CNTL, |
1651 | M98088_REC_LINEMODE_MASK, val: regval); |
1652 | |
1653 | /* Configure equalizers */ |
1654 | if (pdata->eq_cfgcnt) |
1655 | max98088_handle_eq_pdata(component); |
1656 | } |
1657 | |
1658 | static int max98088_probe(struct snd_soc_component *component) |
1659 | { |
1660 | struct max98088_priv *max98088 = snd_soc_component_get_drvdata(c: component); |
1661 | struct max98088_cdata *cdata; |
1662 | int ret = 0; |
1663 | |
1664 | regcache_mark_dirty(map: max98088->regmap); |
1665 | |
1666 | /* initialize private data */ |
1667 | |
1668 | max98088->sysclk = (unsigned)-1; |
1669 | max98088->eq_textcnt = 0; |
1670 | |
1671 | cdata = &max98088->dai[0]; |
1672 | cdata->rate = (unsigned)-1; |
1673 | cdata->fmt = (unsigned)-1; |
1674 | cdata->eq_sel = 0; |
1675 | |
1676 | cdata = &max98088->dai[1]; |
1677 | cdata->rate = (unsigned)-1; |
1678 | cdata->fmt = (unsigned)-1; |
1679 | cdata->eq_sel = 0; |
1680 | |
1681 | max98088->ina_state = 0; |
1682 | max98088->inb_state = 0; |
1683 | max98088->ex_mode = 0; |
1684 | max98088->digmic = 0; |
1685 | max98088->mic1pre = 0; |
1686 | max98088->mic2pre = 0; |
1687 | |
1688 | ret = snd_soc_component_read(component, M98088_REG_FF_REV_ID); |
1689 | if (ret < 0) { |
1690 | dev_err(component->dev, "Failed to read device revision: %d\n" , |
1691 | ret); |
1692 | goto err_access; |
1693 | } |
1694 | dev_info(component->dev, "revision %c\n" , ret - 0x40 + 'A'); |
1695 | |
1696 | snd_soc_component_write(component, M98088_REG_51_PWR_SYS, M98088_PWRSV); |
1697 | |
1698 | snd_soc_component_write(component, M98088_REG_0F_IRQ_ENABLE, val: 0x00); |
1699 | |
1700 | snd_soc_component_write(component, M98088_REG_22_MIX_DAC, |
1701 | M98088_DAI1L_TO_DACL|M98088_DAI2L_TO_DACL| |
1702 | M98088_DAI1R_TO_DACR|M98088_DAI2R_TO_DACR); |
1703 | |
1704 | snd_soc_component_write(component, M98088_REG_4E_BIAS_CNTL, val: 0xF0); |
1705 | snd_soc_component_write(component, M98088_REG_50_DAC_BIAS2, val: 0x0F); |
1706 | |
1707 | snd_soc_component_write(component, M98088_REG_16_DAI1_IOCFG, |
1708 | M98088_S1NORMAL|M98088_SDATA); |
1709 | |
1710 | snd_soc_component_write(component, M98088_REG_1E_DAI2_IOCFG, |
1711 | M98088_S2NORMAL|M98088_SDATA); |
1712 | |
1713 | max98088_handle_pdata(component); |
1714 | |
1715 | err_access: |
1716 | return ret; |
1717 | } |
1718 | |
1719 | static void max98088_remove(struct snd_soc_component *component) |
1720 | { |
1721 | struct max98088_priv *max98088 = snd_soc_component_get_drvdata(c: component); |
1722 | |
1723 | kfree(objp: max98088->eq_texts); |
1724 | } |
1725 | |
1726 | static const struct snd_soc_component_driver soc_component_dev_max98088 = { |
1727 | .probe = max98088_probe, |
1728 | .remove = max98088_remove, |
1729 | .set_bias_level = max98088_set_bias_level, |
1730 | .controls = max98088_snd_controls, |
1731 | .num_controls = ARRAY_SIZE(max98088_snd_controls), |
1732 | .dapm_widgets = max98088_dapm_widgets, |
1733 | .num_dapm_widgets = ARRAY_SIZE(max98088_dapm_widgets), |
1734 | .dapm_routes = max98088_audio_map, |
1735 | .num_dapm_routes = ARRAY_SIZE(max98088_audio_map), |
1736 | .suspend_bias_off = 1, |
1737 | .idle_bias_on = 1, |
1738 | .use_pmdown_time = 1, |
1739 | .endianness = 1, |
1740 | }; |
1741 | |
1742 | static const struct i2c_device_id max98088_i2c_id[] = { |
1743 | { "max98088" , MAX98088 }, |
1744 | { "max98089" , MAX98089 }, |
1745 | { } |
1746 | }; |
1747 | MODULE_DEVICE_TABLE(i2c, max98088_i2c_id); |
1748 | |
1749 | static int max98088_i2c_probe(struct i2c_client *i2c) |
1750 | { |
1751 | struct max98088_priv *max98088; |
1752 | const struct i2c_device_id *id; |
1753 | |
1754 | max98088 = devm_kzalloc(dev: &i2c->dev, size: sizeof(struct max98088_priv), |
1755 | GFP_KERNEL); |
1756 | if (max98088 == NULL) |
1757 | return -ENOMEM; |
1758 | |
1759 | max98088->regmap = devm_regmap_init_i2c(i2c, &max98088_regmap); |
1760 | if (IS_ERR(ptr: max98088->regmap)) |
1761 | return PTR_ERR(ptr: max98088->regmap); |
1762 | |
1763 | max98088->mclk = devm_clk_get(dev: &i2c->dev, id: "mclk" ); |
1764 | if (IS_ERR(ptr: max98088->mclk)) |
1765 | if (PTR_ERR(ptr: max98088->mclk) == -EPROBE_DEFER) |
1766 | return PTR_ERR(ptr: max98088->mclk); |
1767 | |
1768 | id = i2c_match_id(id: max98088_i2c_id, client: i2c); |
1769 | max98088->devtype = id->driver_data; |
1770 | |
1771 | i2c_set_clientdata(client: i2c, data: max98088); |
1772 | max98088->pdata = i2c->dev.platform_data; |
1773 | |
1774 | return devm_snd_soc_register_component(dev: &i2c->dev, component_driver: &soc_component_dev_max98088, |
1775 | dai_drv: &max98088_dai[0], num_dai: 2); |
1776 | } |
1777 | |
1778 | #if defined(CONFIG_OF) |
1779 | static const struct of_device_id max98088_of_match[] = { |
1780 | { .compatible = "maxim,max98088" }, |
1781 | { .compatible = "maxim,max98089" }, |
1782 | { } |
1783 | }; |
1784 | MODULE_DEVICE_TABLE(of, max98088_of_match); |
1785 | #endif |
1786 | |
1787 | static struct i2c_driver max98088_i2c_driver = { |
1788 | .driver = { |
1789 | .name = "max98088" , |
1790 | .of_match_table = of_match_ptr(max98088_of_match), |
1791 | }, |
1792 | .probe = max98088_i2c_probe, |
1793 | .id_table = max98088_i2c_id, |
1794 | }; |
1795 | |
1796 | module_i2c_driver(max98088_i2c_driver); |
1797 | |
1798 | MODULE_DESCRIPTION("ALSA SoC MAX98088 driver" ); |
1799 | MODULE_AUTHOR("Peter Hsiang, Jesse Marroquin" ); |
1800 | MODULE_LICENSE("GPL" ); |
1801 | |