diff options
Diffstat (limited to 'sound/soc/codecs/max98088.c')
-rw-r--r-- | sound/soc/codecs/max98088.c | 2097 |
1 files changed, 2097 insertions, 0 deletions
diff --git a/sound/soc/codecs/max98088.c b/sound/soc/codecs/max98088.c new file mode 100644 index 000000000000..e7a40d16df90 --- /dev/null +++ b/sound/soc/codecs/max98088.c | |||
@@ -0,0 +1,2097 @@ | |||
1 | /* | ||
2 | * max98088.c -- MAX98088 ALSA SoC Audio driver | ||
3 | * | ||
4 | * Copyright 2010 Maxim Integrated Products | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | */ | ||
10 | |||
11 | #include <linux/module.h> | ||
12 | #include <linux/moduleparam.h> | ||
13 | #include <linux/kernel.h> | ||
14 | #include <linux/init.h> | ||
15 | #include <linux/delay.h> | ||
16 | #include <linux/pm.h> | ||
17 | #include <linux/i2c.h> | ||
18 | #include <linux/platform_device.h> | ||
19 | #include <sound/core.h> | ||
20 | #include <sound/pcm.h> | ||
21 | #include <sound/pcm_params.h> | ||
22 | #include <sound/soc.h> | ||
23 | #include <sound/soc-dapm.h> | ||
24 | #include <sound/initval.h> | ||
25 | #include <sound/tlv.h> | ||
26 | #include <linux/slab.h> | ||
27 | #include <asm/div64.h> | ||
28 | #include <sound/max98088.h> | ||
29 | #include "max98088.h" | ||
30 | |||
31 | struct max98088_cdata { | ||
32 | unsigned int rate; | ||
33 | unsigned int fmt; | ||
34 | int eq_sel; | ||
35 | }; | ||
36 | |||
37 | struct max98088_priv { | ||
38 | u8 reg_cache[M98088_REG_CNT]; | ||
39 | void *control_data; | ||
40 | struct max98088_pdata *pdata; | ||
41 | unsigned int sysclk; | ||
42 | struct max98088_cdata dai[2]; | ||
43 | int eq_textcnt; | ||
44 | const char **eq_texts; | ||
45 | struct soc_enum eq_enum; | ||
46 | u8 ina_state; | ||
47 | u8 inb_state; | ||
48 | unsigned int ex_mode; | ||
49 | unsigned int digmic; | ||
50 | unsigned int mic1pre; | ||
51 | unsigned int mic2pre; | ||
52 | unsigned int extmic_mode; | ||
53 | }; | ||
54 | |||
55 | static const u8 max98088_reg[M98088_REG_CNT] = { | ||
56 | 0x00, /* 00 IRQ status */ | ||
57 | 0x00, /* 01 MIC status */ | ||
58 | 0x00, /* 02 jack status */ | ||
59 | 0x00, /* 03 battery voltage */ | ||
60 | 0x00, /* 04 */ | ||
61 | 0x00, /* 05 */ | ||
62 | 0x00, /* 06 */ | ||
63 | 0x00, /* 07 */ | ||
64 | 0x00, /* 08 */ | ||
65 | 0x00, /* 09 */ | ||
66 | 0x00, /* 0A */ | ||
67 | 0x00, /* 0B */ | ||
68 | 0x00, /* 0C */ | ||
69 | 0x00, /* 0D */ | ||
70 | 0x00, /* 0E */ | ||
71 | 0x00, /* 0F interrupt enable */ | ||
72 | |||
73 | 0x00, /* 10 master clock */ | ||
74 | 0x00, /* 11 DAI1 clock mode */ | ||
75 | 0x00, /* 12 DAI1 clock control */ | ||
76 | 0x00, /* 13 DAI1 clock control */ | ||
77 | 0x00, /* 14 DAI1 format */ | ||
78 | 0x00, /* 15 DAI1 clock */ | ||
79 | 0x00, /* 16 DAI1 config */ | ||
80 | 0x00, /* 17 DAI1 TDM */ | ||
81 | 0x00, /* 18 DAI1 filters */ | ||
82 | 0x00, /* 19 DAI2 clock mode */ | ||
83 | 0x00, /* 1A DAI2 clock control */ | ||
84 | 0x00, /* 1B DAI2 clock control */ | ||
85 | 0x00, /* 1C DAI2 format */ | ||
86 | 0x00, /* 1D DAI2 clock */ | ||
87 | 0x00, /* 1E DAI2 config */ | ||
88 | 0x00, /* 1F DAI2 TDM */ | ||
89 | |||
90 | 0x00, /* 20 DAI2 filters */ | ||
91 | 0x00, /* 21 data config */ | ||
92 | 0x00, /* 22 DAC mixer */ | ||
93 | 0x00, /* 23 left ADC mixer */ | ||
94 | 0x00, /* 24 right ADC mixer */ | ||
95 | 0x00, /* 25 left HP mixer */ | ||
96 | 0x00, /* 26 right HP mixer */ | ||
97 | 0x00, /* 27 HP control */ | ||
98 | 0x00, /* 28 left REC mixer */ | ||
99 | 0x00, /* 29 right REC mixer */ | ||
100 | 0x00, /* 2A REC control */ | ||
101 | 0x00, /* 2B left SPK mixer */ | ||
102 | 0x00, /* 2C right SPK mixer */ | ||
103 | 0x00, /* 2D SPK control */ | ||
104 | 0x00, /* 2E sidetone */ | ||
105 | 0x00, /* 2F DAI1 playback level */ | ||
106 | |||
107 | 0x00, /* 30 DAI1 playback level */ | ||
108 | 0x00, /* 31 DAI2 playback level */ | ||
109 | 0x00, /* 32 DAI2 playbakc level */ | ||
110 | 0x00, /* 33 left ADC level */ | ||
111 | 0x00, /* 34 right ADC level */ | ||
112 | 0x00, /* 35 MIC1 level */ | ||
113 | 0x00, /* 36 MIC2 level */ | ||
114 | 0x00, /* 37 INA level */ | ||
115 | 0x00, /* 38 INB level */ | ||
116 | 0x00, /* 39 left HP volume */ | ||
117 | 0x00, /* 3A right HP volume */ | ||
118 | 0x00, /* 3B left REC volume */ | ||
119 | 0x00, /* 3C right REC volume */ | ||
120 | 0x00, /* 3D left SPK volume */ | ||
121 | 0x00, /* 3E right SPK volume */ | ||
122 | 0x00, /* 3F MIC config */ | ||
123 | |||
124 | 0x00, /* 40 MIC threshold */ | ||
125 | 0x00, /* 41 excursion limiter filter */ | ||
126 | 0x00, /* 42 excursion limiter threshold */ | ||
127 | 0x00, /* 43 ALC */ | ||
128 | 0x00, /* 44 power limiter threshold */ | ||
129 | 0x00, /* 45 power limiter config */ | ||
130 | 0x00, /* 46 distortion limiter config */ | ||
131 | 0x00, /* 47 audio input */ | ||
132 | 0x00, /* 48 microphone */ | ||
133 | 0x00, /* 49 level control */ | ||
134 | 0x00, /* 4A bypass switches */ | ||
135 | 0x00, /* 4B jack detect */ | ||
136 | 0x00, /* 4C input enable */ | ||
137 | 0x00, /* 4D output enable */ | ||
138 | 0xF0, /* 4E bias control */ | ||
139 | 0x00, /* 4F DAC power */ | ||
140 | |||
141 | 0x0F, /* 50 DAC power */ | ||
142 | 0x00, /* 51 system */ | ||
143 | 0x00, /* 52 DAI1 EQ1 */ | ||
144 | 0x00, /* 53 DAI1 EQ1 */ | ||
145 | 0x00, /* 54 DAI1 EQ1 */ | ||
146 | 0x00, /* 55 DAI1 EQ1 */ | ||
147 | 0x00, /* 56 DAI1 EQ1 */ | ||
148 | 0x00, /* 57 DAI1 EQ1 */ | ||
149 | 0x00, /* 58 DAI1 EQ1 */ | ||
150 | 0x00, /* 59 DAI1 EQ1 */ | ||
151 | 0x00, /* 5A DAI1 EQ1 */ | ||
152 | 0x00, /* 5B DAI1 EQ1 */ | ||
153 | 0x00, /* 5C DAI1 EQ2 */ | ||
154 | 0x00, /* 5D DAI1 EQ2 */ | ||
155 | 0x00, /* 5E DAI1 EQ2 */ | ||
156 | 0x00, /* 5F DAI1 EQ2 */ | ||
157 | |||
158 | 0x00, /* 60 DAI1 EQ2 */ | ||
159 | 0x00, /* 61 DAI1 EQ2 */ | ||
160 | 0x00, /* 62 DAI1 EQ2 */ | ||
161 | 0x00, /* 63 DAI1 EQ2 */ | ||
162 | 0x00, /* 64 DAI1 EQ2 */ | ||
163 | 0x00, /* 65 DAI1 EQ2 */ | ||
164 | 0x00, /* 66 DAI1 EQ3 */ | ||
165 | 0x00, /* 67 DAI1 EQ3 */ | ||
166 | 0x00, /* 68 DAI1 EQ3 */ | ||
167 | 0x00, /* 69 DAI1 EQ3 */ | ||
168 | 0x00, /* 6A DAI1 EQ3 */ | ||
169 | 0x00, /* 6B DAI1 EQ3 */ | ||
170 | 0x00, /* 6C DAI1 EQ3 */ | ||
171 | 0x00, /* 6D DAI1 EQ3 */ | ||
172 | 0x00, /* 6E DAI1 EQ3 */ | ||
173 | 0x00, /* 6F DAI1 EQ3 */ | ||
174 | |||
175 | 0x00, /* 70 DAI1 EQ4 */ | ||
176 | 0x00, /* 71 DAI1 EQ4 */ | ||
177 | 0x00, /* 72 DAI1 EQ4 */ | ||
178 | 0x00, /* 73 DAI1 EQ4 */ | ||
179 | 0x00, /* 74 DAI1 EQ4 */ | ||
180 | 0x00, /* 75 DAI1 EQ4 */ | ||
181 | 0x00, /* 76 DAI1 EQ4 */ | ||
182 | 0x00, /* 77 DAI1 EQ4 */ | ||
183 | 0x00, /* 78 DAI1 EQ4 */ | ||
184 | 0x00, /* 79 DAI1 EQ4 */ | ||
185 | 0x00, /* 7A DAI1 EQ5 */ | ||
186 | 0x00, /* 7B DAI1 EQ5 */ | ||
187 | 0x00, /* 7C DAI1 EQ5 */ | ||
188 | 0x00, /* 7D DAI1 EQ5 */ | ||
189 | 0x00, /* 7E DAI1 EQ5 */ | ||
190 | 0x00, /* 7F DAI1 EQ5 */ | ||
191 | |||
192 | 0x00, /* 80 DAI1 EQ5 */ | ||
193 | 0x00, /* 81 DAI1 EQ5 */ | ||
194 | 0x00, /* 82 DAI1 EQ5 */ | ||
195 | 0x00, /* 83 DAI1 EQ5 */ | ||
196 | 0x00, /* 84 DAI2 EQ1 */ | ||
197 | 0x00, /* 85 DAI2 EQ1 */ | ||
198 | 0x00, /* 86 DAI2 EQ1 */ | ||
199 | 0x00, /* 87 DAI2 EQ1 */ | ||
200 | 0x00, /* 88 DAI2 EQ1 */ | ||
201 | 0x00, /* 89 DAI2 EQ1 */ | ||
202 | 0x00, /* 8A DAI2 EQ1 */ | ||
203 | 0x00, /* 8B DAI2 EQ1 */ | ||
204 | 0x00, /* 8C DAI2 EQ1 */ | ||
205 | 0x00, /* 8D DAI2 EQ1 */ | ||
206 | 0x00, /* 8E DAI2 EQ2 */ | ||
207 | 0x00, /* 8F DAI2 EQ2 */ | ||
208 | |||
209 | 0x00, /* 90 DAI2 EQ2 */ | ||
210 | 0x00, /* 91 DAI2 EQ2 */ | ||
211 | 0x00, /* 92 DAI2 EQ2 */ | ||
212 | 0x00, /* 93 DAI2 EQ2 */ | ||
213 | 0x00, /* 94 DAI2 EQ2 */ | ||
214 | 0x00, /* 95 DAI2 EQ2 */ | ||
215 | 0x00, /* 96 DAI2 EQ2 */ | ||
216 | 0x00, /* 97 DAI2 EQ2 */ | ||
217 | 0x00, /* 98 DAI2 EQ3 */ | ||
218 | 0x00, /* 99 DAI2 EQ3 */ | ||
219 | 0x00, /* 9A DAI2 EQ3 */ | ||
220 | 0x00, /* 9B DAI2 EQ3 */ | ||
221 | 0x00, /* 9C DAI2 EQ3 */ | ||
222 | 0x00, /* 9D DAI2 EQ3 */ | ||
223 | 0x00, /* 9E DAI2 EQ3 */ | ||
224 | 0x00, /* 9F DAI2 EQ3 */ | ||
225 | |||
226 | 0x00, /* A0 DAI2 EQ3 */ | ||
227 | 0x00, /* A1 DAI2 EQ3 */ | ||
228 | 0x00, /* A2 DAI2 EQ4 */ | ||
229 | 0x00, /* A3 DAI2 EQ4 */ | ||
230 | 0x00, /* A4 DAI2 EQ4 */ | ||
231 | 0x00, /* A5 DAI2 EQ4 */ | ||
232 | 0x00, /* A6 DAI2 EQ4 */ | ||
233 | 0x00, /* A7 DAI2 EQ4 */ | ||
234 | 0x00, /* A8 DAI2 EQ4 */ | ||
235 | 0x00, /* A9 DAI2 EQ4 */ | ||
236 | 0x00, /* AA DAI2 EQ4 */ | ||
237 | 0x00, /* AB DAI2 EQ4 */ | ||
238 | 0x00, /* AC DAI2 EQ5 */ | ||
239 | 0x00, /* AD DAI2 EQ5 */ | ||
240 | 0x00, /* AE DAI2 EQ5 */ | ||
241 | 0x00, /* AF DAI2 EQ5 */ | ||
242 | |||
243 | 0x00, /* B0 DAI2 EQ5 */ | ||
244 | 0x00, /* B1 DAI2 EQ5 */ | ||
245 | 0x00, /* B2 DAI2 EQ5 */ | ||
246 | 0x00, /* B3 DAI2 EQ5 */ | ||
247 | 0x00, /* B4 DAI2 EQ5 */ | ||
248 | 0x00, /* B5 DAI2 EQ5 */ | ||
249 | 0x00, /* B6 DAI1 biquad */ | ||
250 | 0x00, /* B7 DAI1 biquad */ | ||
251 | 0x00, /* B8 DAI1 biquad */ | ||
252 | 0x00, /* B9 DAI1 biquad */ | ||
253 | 0x00, /* BA DAI1 biquad */ | ||
254 | 0x00, /* BB DAI1 biquad */ | ||
255 | 0x00, /* BC DAI1 biquad */ | ||
256 | 0x00, /* BD DAI1 biquad */ | ||
257 | 0x00, /* BE DAI1 biquad */ | ||
258 | 0x00, /* BF DAI1 biquad */ | ||
259 | |||
260 | 0x00, /* C0 DAI2 biquad */ | ||
261 | 0x00, /* C1 DAI2 biquad */ | ||
262 | 0x00, /* C2 DAI2 biquad */ | ||
263 | 0x00, /* C3 DAI2 biquad */ | ||
264 | 0x00, /* C4 DAI2 biquad */ | ||
265 | 0x00, /* C5 DAI2 biquad */ | ||
266 | 0x00, /* C6 DAI2 biquad */ | ||
267 | 0x00, /* C7 DAI2 biquad */ | ||
268 | 0x00, /* C8 DAI2 biquad */ | ||
269 | 0x00, /* C9 DAI2 biquad */ | ||
270 | 0x00, /* CA */ | ||
271 | 0x00, /* CB */ | ||
272 | 0x00, /* CC */ | ||
273 | 0x00, /* CD */ | ||
274 | 0x00, /* CE */ | ||
275 | 0x00, /* CF */ | ||
276 | |||
277 | 0x00, /* D0 */ | ||
278 | 0x00, /* D1 */ | ||
279 | 0x00, /* D2 */ | ||
280 | 0x00, /* D3 */ | ||
281 | 0x00, /* D4 */ | ||
282 | 0x00, /* D5 */ | ||
283 | 0x00, /* D6 */ | ||
284 | 0x00, /* D7 */ | ||
285 | 0x00, /* D8 */ | ||
286 | 0x00, /* D9 */ | ||
287 | 0x00, /* DA */ | ||
288 | 0x70, /* DB */ | ||
289 | 0x00, /* DC */ | ||
290 | 0x00, /* DD */ | ||
291 | 0x00, /* DE */ | ||
292 | 0x00, /* DF */ | ||
293 | |||
294 | 0x00, /* E0 */ | ||
295 | 0x00, /* E1 */ | ||
296 | 0x00, /* E2 */ | ||
297 | 0x00, /* E3 */ | ||
298 | 0x00, /* E4 */ | ||
299 | 0x00, /* E5 */ | ||
300 | 0x00, /* E6 */ | ||
301 | 0x00, /* E7 */ | ||
302 | 0x00, /* E8 */ | ||
303 | 0x00, /* E9 */ | ||
304 | 0x00, /* EA */ | ||
305 | 0x00, /* EB */ | ||
306 | 0x00, /* EC */ | ||
307 | 0x00, /* ED */ | ||
308 | 0x00, /* EE */ | ||
309 | 0x00, /* EF */ | ||
310 | |||
311 | 0x00, /* F0 */ | ||
312 | 0x00, /* F1 */ | ||
313 | 0x00, /* F2 */ | ||
314 | 0x00, /* F3 */ | ||
315 | 0x00, /* F4 */ | ||
316 | 0x00, /* F5 */ | ||
317 | 0x00, /* F6 */ | ||
318 | 0x00, /* F7 */ | ||
319 | 0x00, /* F8 */ | ||
320 | 0x00, /* F9 */ | ||
321 | 0x00, /* FA */ | ||
322 | 0x00, /* FB */ | ||
323 | 0x00, /* FC */ | ||
324 | 0x00, /* FD */ | ||
325 | 0x00, /* FE */ | ||
326 | 0x00, /* FF */ | ||
327 | }; | ||
328 | |||
329 | static struct { | ||
330 | int readable; | ||
331 | int writable; | ||
332 | int vol; | ||
333 | } max98088_access[M98088_REG_CNT] = { | ||
334 | { 0xFF, 0xFF, 1 }, /* 00 IRQ status */ | ||
335 | { 0xFF, 0x00, 1 }, /* 01 MIC status */ | ||
336 | { 0xFF, 0x00, 1 }, /* 02 jack status */ | ||
337 | { 0x1F, 0x1F, 1 }, /* 03 battery voltage */ | ||
338 | { 0xFF, 0xFF, 0 }, /* 04 */ | ||
339 | { 0xFF, 0xFF, 0 }, /* 05 */ | ||
340 | { 0xFF, 0xFF, 0 }, /* 06 */ | ||
341 | { 0xFF, 0xFF, 0 }, /* 07 */ | ||
342 | { 0xFF, 0xFF, 0 }, /* 08 */ | ||
343 | { 0xFF, 0xFF, 0 }, /* 09 */ | ||
344 | { 0xFF, 0xFF, 0 }, /* 0A */ | ||
345 | { 0xFF, 0xFF, 0 }, /* 0B */ | ||
346 | { 0xFF, 0xFF, 0 }, /* 0C */ | ||
347 | { 0xFF, 0xFF, 0 }, /* 0D */ | ||
348 | { 0xFF, 0xFF, 0 }, /* 0E */ | ||
349 | { 0xFF, 0xFF, 0 }, /* 0F interrupt enable */ | ||
350 | |||
351 | { 0xFF, 0xFF, 0 }, /* 10 master clock */ | ||
352 | { 0xFF, 0xFF, 0 }, /* 11 DAI1 clock mode */ | ||
353 | { 0xFF, 0xFF, 0 }, /* 12 DAI1 clock control */ | ||
354 | { 0xFF, 0xFF, 0 }, /* 13 DAI1 clock control */ | ||
355 | { 0xFF, 0xFF, 0 }, /* 14 DAI1 format */ | ||
356 | { 0xFF, 0xFF, 0 }, /* 15 DAI1 clock */ | ||
357 | { 0xFF, 0xFF, 0 }, /* 16 DAI1 config */ | ||
358 | { 0xFF, 0xFF, 0 }, /* 17 DAI1 TDM */ | ||
359 | { 0xFF, 0xFF, 0 }, /* 18 DAI1 filters */ | ||
360 | { 0xFF, 0xFF, 0 }, /* 19 DAI2 clock mode */ | ||
361 | { 0xFF, 0xFF, 0 }, /* 1A DAI2 clock control */ | ||
362 | { 0xFF, 0xFF, 0 }, /* 1B DAI2 clock control */ | ||
363 | { 0xFF, 0xFF, 0 }, /* 1C DAI2 format */ | ||
364 | { 0xFF, 0xFF, 0 }, /* 1D DAI2 clock */ | ||
365 | { 0xFF, 0xFF, 0 }, /* 1E DAI2 config */ | ||
366 | { 0xFF, 0xFF, 0 }, /* 1F DAI2 TDM */ | ||
367 | |||
368 | { 0xFF, 0xFF, 0 }, /* 20 DAI2 filters */ | ||
369 | { 0xFF, 0xFF, 0 }, /* 21 data config */ | ||
370 | { 0xFF, 0xFF, 0 }, /* 22 DAC mixer */ | ||
371 | { 0xFF, 0xFF, 0 }, /* 23 left ADC mixer */ | ||
372 | { 0xFF, 0xFF, 0 }, /* 24 right ADC mixer */ | ||
373 | { 0xFF, 0xFF, 0 }, /* 25 left HP mixer */ | ||
374 | { 0xFF, 0xFF, 0 }, /* 26 right HP mixer */ | ||
375 | { 0xFF, 0xFF, 0 }, /* 27 HP control */ | ||
376 | { 0xFF, 0xFF, 0 }, /* 28 left REC mixer */ | ||
377 | { 0xFF, 0xFF, 0 }, /* 29 right REC mixer */ | ||
378 | { 0xFF, 0xFF, 0 }, /* 2A REC control */ | ||
379 | { 0xFF, 0xFF, 0 }, /* 2B left SPK mixer */ | ||
380 | { 0xFF, 0xFF, 0 }, /* 2C right SPK mixer */ | ||
381 | { 0xFF, 0xFF, 0 }, /* 2D SPK control */ | ||
382 | { 0xFF, 0xFF, 0 }, /* 2E sidetone */ | ||
383 | { 0xFF, 0xFF, 0 }, /* 2F DAI1 playback level */ | ||
384 | |||
385 | { 0xFF, 0xFF, 0 }, /* 30 DAI1 playback level */ | ||
386 | { 0xFF, 0xFF, 0 }, /* 31 DAI2 playback level */ | ||
387 | { 0xFF, 0xFF, 0 }, /* 32 DAI2 playbakc level */ | ||
388 | { 0xFF, 0xFF, 0 }, /* 33 left ADC level */ | ||
389 | { 0xFF, 0xFF, 0 }, /* 34 right ADC level */ | ||
390 | { 0xFF, 0xFF, 0 }, /* 35 MIC1 level */ | ||
391 | { 0xFF, 0xFF, 0 }, /* 36 MIC2 level */ | ||
392 | { 0xFF, 0xFF, 0 }, /* 37 INA level */ | ||
393 | { 0xFF, 0xFF, 0 }, /* 38 INB level */ | ||
394 | { 0xFF, 0xFF, 0 }, /* 39 left HP volume */ | ||
395 | { 0xFF, 0xFF, 0 }, /* 3A right HP volume */ | ||
396 | { 0xFF, 0xFF, 0 }, /* 3B left REC volume */ | ||
397 | { 0xFF, 0xFF, 0 }, /* 3C right REC volume */ | ||
398 | { 0xFF, 0xFF, 0 }, /* 3D left SPK volume */ | ||
399 | { 0xFF, 0xFF, 0 }, /* 3E right SPK volume */ | ||
400 | { 0xFF, 0xFF, 0 }, /* 3F MIC config */ | ||
401 | |||
402 | { 0xFF, 0xFF, 0 }, /* 40 MIC threshold */ | ||
403 | { 0xFF, 0xFF, 0 }, /* 41 excursion limiter filter */ | ||
404 | { 0xFF, 0xFF, 0 }, /* 42 excursion limiter threshold */ | ||
405 | { 0xFF, 0xFF, 0 }, /* 43 ALC */ | ||
406 | { 0xFF, 0xFF, 0 }, /* 44 power limiter threshold */ | ||
407 | { 0xFF, 0xFF, 0 }, /* 45 power limiter config */ | ||
408 | { 0xFF, 0xFF, 0 }, /* 46 distortion limiter config */ | ||
409 | { 0xFF, 0xFF, 0 }, /* 47 audio input */ | ||
410 | { 0xFF, 0xFF, 0 }, /* 48 microphone */ | ||
411 | { 0xFF, 0xFF, 0 }, /* 49 level control */ | ||
412 | { 0xFF, 0xFF, 0 }, /* 4A bypass switches */ | ||
413 | { 0xFF, 0xFF, 0 }, /* 4B jack detect */ | ||
414 | { 0xFF, 0xFF, 0 }, /* 4C input enable */ | ||
415 | { 0xFF, 0xFF, 0 }, /* 4D output enable */ | ||
416 | { 0xFF, 0xFF, 0 }, /* 4E bias control */ | ||
417 | { 0xFF, 0xFF, 0 }, /* 4F DAC power */ | ||
418 | |||
419 | { 0xFF, 0xFF, 0 }, /* 50 DAC power */ | ||
420 | { 0xFF, 0xFF, 0 }, /* 51 system */ | ||
421 | { 0xFF, 0xFF, 0 }, /* 52 DAI1 EQ1 */ | ||
422 | { 0xFF, 0xFF, 0 }, /* 53 DAI1 EQ1 */ | ||
423 | { 0xFF, 0xFF, 0 }, /* 54 DAI1 EQ1 */ | ||
424 | { 0xFF, 0xFF, 0 }, /* 55 DAI1 EQ1 */ | ||
425 | { 0xFF, 0xFF, 0 }, /* 56 DAI1 EQ1 */ | ||
426 | { 0xFF, 0xFF, 0 }, /* 57 DAI1 EQ1 */ | ||
427 | { 0xFF, 0xFF, 0 }, /* 58 DAI1 EQ1 */ | ||
428 | { 0xFF, 0xFF, 0 }, /* 59 DAI1 EQ1 */ | ||
429 | { 0xFF, 0xFF, 0 }, /* 5A DAI1 EQ1 */ | ||
430 | { 0xFF, 0xFF, 0 }, /* 5B DAI1 EQ1 */ | ||
431 | { 0xFF, 0xFF, 0 }, /* 5C DAI1 EQ2 */ | ||
432 | { 0xFF, 0xFF, 0 }, /* 5D DAI1 EQ2 */ | ||
433 | { 0xFF, 0xFF, 0 }, /* 5E DAI1 EQ2 */ | ||
434 | { 0xFF, 0xFF, 0 }, /* 5F DAI1 EQ2 */ | ||
435 | |||
436 | { 0xFF, 0xFF, 0 }, /* 60 DAI1 EQ2 */ | ||
437 | { 0xFF, 0xFF, 0 }, /* 61 DAI1 EQ2 */ | ||
438 | { 0xFF, 0xFF, 0 }, /* 62 DAI1 EQ2 */ | ||
439 | { 0xFF, 0xFF, 0 }, /* 63 DAI1 EQ2 */ | ||
440 | { 0xFF, 0xFF, 0 }, /* 64 DAI1 EQ2 */ | ||
441 | { 0xFF, 0xFF, 0 }, /* 65 DAI1 EQ2 */ | ||
442 | { 0xFF, 0xFF, 0 }, /* 66 DAI1 EQ3 */ | ||
443 | { 0xFF, 0xFF, 0 }, /* 67 DAI1 EQ3 */ | ||
444 | { 0xFF, 0xFF, 0 }, /* 68 DAI1 EQ3 */ | ||
445 | { 0xFF, 0xFF, 0 }, /* 69 DAI1 EQ3 */ | ||
446 | { 0xFF, 0xFF, 0 }, /* 6A DAI1 EQ3 */ | ||
447 | { 0xFF, 0xFF, 0 }, /* 6B DAI1 EQ3 */ | ||
448 | { 0xFF, 0xFF, 0 }, /* 6C DAI1 EQ3 */ | ||
449 | { 0xFF, 0xFF, 0 }, /* 6D DAI1 EQ3 */ | ||
450 | { 0xFF, 0xFF, 0 }, /* 6E DAI1 EQ3 */ | ||
451 | { 0xFF, 0xFF, 0 }, /* 6F DAI1 EQ3 */ | ||
452 | |||
453 | { 0xFF, 0xFF, 0 }, /* 70 DAI1 EQ4 */ | ||
454 | { 0xFF, 0xFF, 0 }, /* 71 DAI1 EQ4 */ | ||
455 | { 0xFF, 0xFF, 0 }, /* 72 DAI1 EQ4 */ | ||
456 | { 0xFF, 0xFF, 0 }, /* 73 DAI1 EQ4 */ | ||
457 | { 0xFF, 0xFF, 0 }, /* 74 DAI1 EQ4 */ | ||
458 | { 0xFF, 0xFF, 0 }, /* 75 DAI1 EQ4 */ | ||
459 | { 0xFF, 0xFF, 0 }, /* 76 DAI1 EQ4 */ | ||
460 | { 0xFF, 0xFF, 0 }, /* 77 DAI1 EQ4 */ | ||
461 | { 0xFF, 0xFF, 0 }, /* 78 DAI1 EQ4 */ | ||
462 | { 0xFF, 0xFF, 0 }, /* 79 DAI1 EQ4 */ | ||
463 | { 0xFF, 0xFF, 0 }, /* 7A DAI1 EQ5 */ | ||
464 | { 0xFF, 0xFF, 0 }, /* 7B DAI1 EQ5 */ | ||
465 | { 0xFF, 0xFF, 0 }, /* 7C DAI1 EQ5 */ | ||
466 | { 0xFF, 0xFF, 0 }, /* 7D DAI1 EQ5 */ | ||
467 | { 0xFF, 0xFF, 0 }, /* 7E DAI1 EQ5 */ | ||
468 | { 0xFF, 0xFF, 0 }, /* 7F DAI1 EQ5 */ | ||
469 | |||
470 | { 0xFF, 0xFF, 0 }, /* 80 DAI1 EQ5 */ | ||
471 | { 0xFF, 0xFF, 0 }, /* 81 DAI1 EQ5 */ | ||
472 | { 0xFF, 0xFF, 0 }, /* 82 DAI1 EQ5 */ | ||
473 | { 0xFF, 0xFF, 0 }, /* 83 DAI1 EQ5 */ | ||
474 | { 0xFF, 0xFF, 0 }, /* 84 DAI2 EQ1 */ | ||
475 | { 0xFF, 0xFF, 0 }, /* 85 DAI2 EQ1 */ | ||
476 | { 0xFF, 0xFF, 0 }, /* 86 DAI2 EQ1 */ | ||
477 | { 0xFF, 0xFF, 0 }, /* 87 DAI2 EQ1 */ | ||
478 | { 0xFF, 0xFF, 0 }, /* 88 DAI2 EQ1 */ | ||
479 | { 0xFF, 0xFF, 0 }, /* 89 DAI2 EQ1 */ | ||
480 | { 0xFF, 0xFF, 0 }, /* 8A DAI2 EQ1 */ | ||
481 | { 0xFF, 0xFF, 0 }, /* 8B DAI2 EQ1 */ | ||
482 | { 0xFF, 0xFF, 0 }, /* 8C DAI2 EQ1 */ | ||
483 | { 0xFF, 0xFF, 0 }, /* 8D DAI2 EQ1 */ | ||
484 | { 0xFF, 0xFF, 0 }, /* 8E DAI2 EQ2 */ | ||
485 | { 0xFF, 0xFF, 0 }, /* 8F DAI2 EQ2 */ | ||
486 | |||
487 | { 0xFF, 0xFF, 0 }, /* 90 DAI2 EQ2 */ | ||
488 | { 0xFF, 0xFF, 0 }, /* 91 DAI2 EQ2 */ | ||
489 | { 0xFF, 0xFF, 0 }, /* 92 DAI2 EQ2 */ | ||
490 | { 0xFF, 0xFF, 0 }, /* 93 DAI2 EQ2 */ | ||
491 | { 0xFF, 0xFF, 0 }, /* 94 DAI2 EQ2 */ | ||
492 | { 0xFF, 0xFF, 0 }, /* 95 DAI2 EQ2 */ | ||
493 | { 0xFF, 0xFF, 0 }, /* 96 DAI2 EQ2 */ | ||
494 | { 0xFF, 0xFF, 0 }, /* 97 DAI2 EQ2 */ | ||
495 | { 0xFF, 0xFF, 0 }, /* 98 DAI2 EQ3 */ | ||
496 | { 0xFF, 0xFF, 0 }, /* 99 DAI2 EQ3 */ | ||
497 | { 0xFF, 0xFF, 0 }, /* 9A DAI2 EQ3 */ | ||
498 | { 0xFF, 0xFF, 0 }, /* 9B DAI2 EQ3 */ | ||
499 | { 0xFF, 0xFF, 0 }, /* 9C DAI2 EQ3 */ | ||
500 | { 0xFF, 0xFF, 0 }, /* 9D DAI2 EQ3 */ | ||
501 | { 0xFF, 0xFF, 0 }, /* 9E DAI2 EQ3 */ | ||
502 | { 0xFF, 0xFF, 0 }, /* 9F DAI2 EQ3 */ | ||
503 | |||
504 | { 0xFF, 0xFF, 0 }, /* A0 DAI2 EQ3 */ | ||
505 | { 0xFF, 0xFF, 0 }, /* A1 DAI2 EQ3 */ | ||
506 | { 0xFF, 0xFF, 0 }, /* A2 DAI2 EQ4 */ | ||
507 | { 0xFF, 0xFF, 0 }, /* A3 DAI2 EQ4 */ | ||
508 | { 0xFF, 0xFF, 0 }, /* A4 DAI2 EQ4 */ | ||
509 | { 0xFF, 0xFF, 0 }, /* A5 DAI2 EQ4 */ | ||
510 | { 0xFF, 0xFF, 0 }, /* A6 DAI2 EQ4 */ | ||
511 | { 0xFF, 0xFF, 0 }, /* A7 DAI2 EQ4 */ | ||
512 | { 0xFF, 0xFF, 0 }, /* A8 DAI2 EQ4 */ | ||
513 | { 0xFF, 0xFF, 0 }, /* A9 DAI2 EQ4 */ | ||
514 | { 0xFF, 0xFF, 0 }, /* AA DAI2 EQ4 */ | ||
515 | { 0xFF, 0xFF, 0 }, /* AB DAI2 EQ4 */ | ||
516 | { 0xFF, 0xFF, 0 }, /* AC DAI2 EQ5 */ | ||
517 | { 0xFF, 0xFF, 0 }, /* AD DAI2 EQ5 */ | ||
518 | { 0xFF, 0xFF, 0 }, /* AE DAI2 EQ5 */ | ||
519 | { 0xFF, 0xFF, 0 }, /* AF DAI2 EQ5 */ | ||
520 | |||
521 | { 0xFF, 0xFF, 0 }, /* B0 DAI2 EQ5 */ | ||
522 | { 0xFF, 0xFF, 0 }, /* B1 DAI2 EQ5 */ | ||
523 | { 0xFF, 0xFF, 0 }, /* B2 DAI2 EQ5 */ | ||
524 | { 0xFF, 0xFF, 0 }, /* B3 DAI2 EQ5 */ | ||
525 | { 0xFF, 0xFF, 0 }, /* B4 DAI2 EQ5 */ | ||
526 | { 0xFF, 0xFF, 0 }, /* B5 DAI2 EQ5 */ | ||
527 | { 0xFF, 0xFF, 0 }, /* B6 DAI1 biquad */ | ||
528 | { 0xFF, 0xFF, 0 }, /* B7 DAI1 biquad */ | ||
529 | { 0xFF, 0xFF, 0 }, /* B8 DAI1 biquad */ | ||
530 | { 0xFF, 0xFF, 0 }, /* B9 DAI1 biquad */ | ||
531 | { 0xFF, 0xFF, 0 }, /* BA DAI1 biquad */ | ||
532 | { 0xFF, 0xFF, 0 }, /* BB DAI1 biquad */ | ||
533 | { 0xFF, 0xFF, 0 }, /* BC DAI1 biquad */ | ||
534 | { 0xFF, 0xFF, 0 }, /* BD DAI1 biquad */ | ||
535 | { 0xFF, 0xFF, 0 }, /* BE DAI1 biquad */ | ||
536 | { 0xFF, 0xFF, 0 }, /* BF DAI1 biquad */ | ||
537 | |||
538 | { 0xFF, 0xFF, 0 }, /* C0 DAI2 biquad */ | ||
539 | { 0xFF, 0xFF, 0 }, /* C1 DAI2 biquad */ | ||
540 | { 0xFF, 0xFF, 0 }, /* C2 DAI2 biquad */ | ||
541 | { 0xFF, 0xFF, 0 }, /* C3 DAI2 biquad */ | ||
542 | { 0xFF, 0xFF, 0 }, /* C4 DAI2 biquad */ | ||
543 | { 0xFF, 0xFF, 0 }, /* C5 DAI2 biquad */ | ||
544 | { 0xFF, 0xFF, 0 }, /* C6 DAI2 biquad */ | ||
545 | { 0xFF, 0xFF, 0 }, /* C7 DAI2 biquad */ | ||
546 | { 0xFF, 0xFF, 0 }, /* C8 DAI2 biquad */ | ||
547 | { 0xFF, 0xFF, 0 }, /* C9 DAI2 biquad */ | ||
548 | { 0x00, 0x00, 0 }, /* CA */ | ||
549 | { 0x00, 0x00, 0 }, /* CB */ | ||
550 | { 0x00, 0x00, 0 }, /* CC */ | ||
551 | { 0x00, 0x00, 0 }, /* CD */ | ||
552 | { 0x00, 0x00, 0 }, /* CE */ | ||
553 | { 0x00, 0x00, 0 }, /* CF */ | ||
554 | |||
555 | { 0x00, 0x00, 0 }, /* D0 */ | ||
556 | { 0x00, 0x00, 0 }, /* D1 */ | ||
557 | { 0x00, 0x00, 0 }, /* D2 */ | ||
558 | { 0x00, 0x00, 0 }, /* D3 */ | ||
559 | { 0x00, 0x00, 0 }, /* D4 */ | ||
560 | { 0x00, 0x00, 0 }, /* D5 */ | ||
561 | { 0x00, 0x00, 0 }, /* D6 */ | ||
562 | { 0x00, 0x00, 0 }, /* D7 */ | ||
563 | { 0x00, 0x00, 0 }, /* D8 */ | ||
564 | { 0x00, 0x00, 0 }, /* D9 */ | ||
565 | { 0x00, 0x00, 0 }, /* DA */ | ||
566 | { 0x00, 0x00, 0 }, /* DB */ | ||
567 | { 0x00, 0x00, 0 }, /* DC */ | ||
568 | { 0x00, 0x00, 0 }, /* DD */ | ||
569 | { 0x00, 0x00, 0 }, /* DE */ | ||
570 | { 0x00, 0x00, 0 }, /* DF */ | ||
571 | |||
572 | { 0x00, 0x00, 0 }, /* E0 */ | ||
573 | { 0x00, 0x00, 0 }, /* E1 */ | ||
574 | { 0x00, 0x00, 0 }, /* E2 */ | ||
575 | { 0x00, 0x00, 0 }, /* E3 */ | ||
576 | { 0x00, 0x00, 0 }, /* E4 */ | ||
577 | { 0x00, 0x00, 0 }, /* E5 */ | ||
578 | { 0x00, 0x00, 0 }, /* E6 */ | ||
579 | { 0x00, 0x00, 0 }, /* E7 */ | ||
580 | { 0x00, 0x00, 0 }, /* E8 */ | ||
581 | { 0x00, 0x00, 0 }, /* E9 */ | ||
582 | { 0x00, 0x00, 0 }, /* EA */ | ||
583 | { 0x00, 0x00, 0 }, /* EB */ | ||
584 | { 0x00, 0x00, 0 }, /* EC */ | ||
585 | { 0x00, 0x00, 0 }, /* ED */ | ||
586 | { 0x00, 0x00, 0 }, /* EE */ | ||
587 | { 0x00, 0x00, 0 }, /* EF */ | ||
588 | |||
589 | { 0x00, 0x00, 0 }, /* F0 */ | ||
590 | { 0x00, 0x00, 0 }, /* F1 */ | ||
591 | { 0x00, 0x00, 0 }, /* F2 */ | ||
592 | { 0x00, 0x00, 0 }, /* F3 */ | ||
593 | { 0x00, 0x00, 0 }, /* F4 */ | ||
594 | { 0x00, 0x00, 0 }, /* F5 */ | ||
595 | { 0x00, 0x00, 0 }, /* F6 */ | ||
596 | { 0x00, 0x00, 0 }, /* F7 */ | ||
597 | { 0x00, 0x00, 0 }, /* F8 */ | ||
598 | { 0x00, 0x00, 0 }, /* F9 */ | ||
599 | { 0x00, 0x00, 0 }, /* FA */ | ||
600 | { 0x00, 0x00, 0 }, /* FB */ | ||
601 | { 0x00, 0x00, 0 }, /* FC */ | ||
602 | { 0x00, 0x00, 0 }, /* FD */ | ||
603 | { 0x00, 0x00, 0 }, /* FE */ | ||
604 | { 0xFF, 0x00, 1 }, /* FF */ | ||
605 | }; | ||
606 | |||
607 | static int max98088_volatile_register(unsigned int reg) | ||
608 | { | ||
609 | return max98088_access[reg].vol; | ||
610 | } | ||
611 | |||
612 | |||
613 | /* | ||
614 | * Load equalizer DSP coefficient configurations registers | ||
615 | */ | ||
616 | static void m98088_eq_band(struct snd_soc_codec *codec, unsigned int dai, | ||
617 | unsigned int band, u16 *coefs) | ||
618 | { | ||
619 | unsigned int eq_reg; | ||
620 | unsigned int i; | ||
621 | |||
622 | BUG_ON(band > 4); | ||
623 | BUG_ON(dai > 1); | ||
624 | |||
625 | /* Load the base register address */ | ||
626 | eq_reg = dai ? M98088_REG_84_DAI2_EQ_BASE : M98088_REG_52_DAI1_EQ_BASE; | ||
627 | |||
628 | /* Add the band address offset, note adjustment for word address */ | ||
629 | eq_reg += band * (M98088_COEFS_PER_BAND << 1); | ||
630 | |||
631 | /* Step through the registers and coefs */ | ||
632 | for (i = 0; i < M98088_COEFS_PER_BAND; i++) { | ||
633 | snd_soc_write(codec, eq_reg++, M98088_BYTE1(coefs[i])); | ||
634 | snd_soc_write(codec, eq_reg++, M98088_BYTE0(coefs[i])); | ||
635 | } | ||
636 | } | ||
637 | |||
638 | /* | ||
639 | * Excursion limiter modes | ||
640 | */ | ||
641 | static const char *max98088_exmode_texts[] = { | ||
642 | "Off", "100Hz", "400Hz", "600Hz", "800Hz", "1000Hz", "200-400Hz", | ||
643 | "400-600Hz", "400-800Hz", | ||
644 | }; | ||
645 | |||
646 | static const unsigned int max98088_exmode_values[] = { | ||
647 | 0x00, 0x43, 0x10, 0x20, 0x30, 0x40, 0x11, 0x22, 0x32 | ||
648 | }; | ||
649 | |||
650 | static const struct soc_enum max98088_exmode_enum = | ||
651 | SOC_VALUE_ENUM_SINGLE(M98088_REG_41_SPKDHP, 0, 127, | ||
652 | ARRAY_SIZE(max98088_exmode_texts), | ||
653 | max98088_exmode_texts, | ||
654 | max98088_exmode_values); | ||
655 | static const struct snd_kcontrol_new max98088_exmode_controls = | ||
656 | SOC_DAPM_VALUE_ENUM("Route", max98088_exmode_enum); | ||
657 | |||
658 | static const char *max98088_ex_thresh[] = { /* volts PP */ | ||
659 | "0.6", "1.2", "1.8", "2.4", "3.0", "3.6", "4.2", "4.8"}; | ||
660 | static const struct soc_enum max98088_ex_thresh_enum[] = { | ||
661 | SOC_ENUM_SINGLE(M98088_REG_42_SPKDHP_THRESH, 0, 8, | ||
662 | max98088_ex_thresh), | ||
663 | }; | ||
664 | |||
665 | static const char *max98088_fltr_mode[] = {"Voice", "Music" }; | ||
666 | static const struct soc_enum max98088_filter_mode_enum[] = { | ||
667 | SOC_ENUM_SINGLE(M98088_REG_18_DAI1_FILTERS, 7, 2, max98088_fltr_mode), | ||
668 | }; | ||
669 | |||
670 | static const char *max98088_extmic_text[] = { "None", "MIC1", "MIC2" }; | ||
671 | |||
672 | static const struct soc_enum max98088_extmic_enum = | ||
673 | SOC_ENUM_SINGLE(M98088_REG_48_CFG_MIC, 0, 3, max98088_extmic_text); | ||
674 | |||
675 | static const struct snd_kcontrol_new max98088_extmic_mux = | ||
676 | SOC_DAPM_ENUM("External MIC Mux", max98088_extmic_enum); | ||
677 | |||
678 | static const char *max98088_dai1_fltr[] = { | ||
679 | "Off", "fc=258/fs=16k", "fc=500/fs=16k", | ||
680 | "fc=258/fs=8k", "fc=500/fs=8k", "fc=200"}; | ||
681 | static const struct soc_enum max98088_dai1_dac_filter_enum[] = { | ||
682 | SOC_ENUM_SINGLE(M98088_REG_18_DAI1_FILTERS, 0, 6, max98088_dai1_fltr), | ||
683 | }; | ||
684 | static const struct soc_enum max98088_dai1_adc_filter_enum[] = { | ||
685 | SOC_ENUM_SINGLE(M98088_REG_18_DAI1_FILTERS, 4, 6, max98088_dai1_fltr), | ||
686 | }; | ||
687 | |||
688 | static int max98088_mic1pre_set(struct snd_kcontrol *kcontrol, | ||
689 | struct snd_ctl_elem_value *ucontrol) | ||
690 | { | ||
691 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | ||
692 | struct max98088_priv *max98088 = snd_soc_codec_get_drvdata(codec); | ||
693 | unsigned int sel = ucontrol->value.integer.value[0]; | ||
694 | |||
695 | max98088->mic1pre = sel; | ||
696 | snd_soc_update_bits(codec, M98088_REG_35_LVL_MIC1, M98088_MICPRE_MASK, | ||
697 | (1+sel)<<M98088_MICPRE_SHIFT); | ||
698 | |||
699 | return 0; | ||
700 | } | ||
701 | |||
702 | static int max98088_mic1pre_get(struct snd_kcontrol *kcontrol, | ||
703 | struct snd_ctl_elem_value *ucontrol) | ||
704 | { | ||
705 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | ||
706 | struct max98088_priv *max98088 = snd_soc_codec_get_drvdata(codec); | ||
707 | |||
708 | ucontrol->value.integer.value[0] = max98088->mic1pre; | ||
709 | return 0; | ||
710 | } | ||
711 | |||
712 | static int max98088_mic2pre_set(struct snd_kcontrol *kcontrol, | ||
713 | struct snd_ctl_elem_value *ucontrol) | ||
714 | { | ||
715 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | ||
716 | struct max98088_priv *max98088 = snd_soc_codec_get_drvdata(codec); | ||
717 | unsigned int sel = ucontrol->value.integer.value[0]; | ||
718 | |||
719 | max98088->mic2pre = sel; | ||
720 | snd_soc_update_bits(codec, M98088_REG_36_LVL_MIC2, M98088_MICPRE_MASK, | ||
721 | (1+sel)<<M98088_MICPRE_SHIFT); | ||
722 | |||
723 | return 0; | ||
724 | } | ||
725 | |||
726 | static int max98088_mic2pre_get(struct snd_kcontrol *kcontrol, | ||
727 | struct snd_ctl_elem_value *ucontrol) | ||
728 | { | ||
729 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | ||
730 | struct max98088_priv *max98088 = snd_soc_codec_get_drvdata(codec); | ||
731 | |||
732 | ucontrol->value.integer.value[0] = max98088->mic2pre; | ||
733 | return 0; | ||
734 | } | ||
735 | |||
736 | static const unsigned int max98088_micboost_tlv[] = { | ||
737 | TLV_DB_RANGE_HEAD(2), | ||
738 | 0, 1, TLV_DB_SCALE_ITEM(0, 2000, 0), | ||
739 | 2, 2, TLV_DB_SCALE_ITEM(3000, 0, 0), | ||
740 | }; | ||
741 | |||
742 | static const struct snd_kcontrol_new max98088_snd_controls[] = { | ||
743 | |||
744 | SOC_DOUBLE_R("Headphone Volume", M98088_REG_39_LVL_HP_L, | ||
745 | M98088_REG_3A_LVL_HP_R, 0, 31, 0), | ||
746 | SOC_DOUBLE_R("Speaker Volume", M98088_REG_3D_LVL_SPK_L, | ||
747 | M98088_REG_3E_LVL_SPK_R, 0, 31, 0), | ||
748 | SOC_DOUBLE_R("Receiver Volume", M98088_REG_3B_LVL_REC_L, | ||
749 | M98088_REG_3C_LVL_REC_R, 0, 31, 0), | ||
750 | |||
751 | SOC_DOUBLE_R("Headphone Switch", M98088_REG_39_LVL_HP_L, | ||
752 | M98088_REG_3A_LVL_HP_R, 7, 1, 1), | ||
753 | SOC_DOUBLE_R("Speaker Switch", M98088_REG_3D_LVL_SPK_L, | ||
754 | M98088_REG_3E_LVL_SPK_R, 7, 1, 1), | ||
755 | SOC_DOUBLE_R("Receiver Switch", M98088_REG_3B_LVL_REC_L, | ||
756 | M98088_REG_3C_LVL_REC_R, 7, 1, 1), | ||
757 | |||
758 | SOC_SINGLE("MIC1 Volume", M98088_REG_35_LVL_MIC1, 0, 31, 1), | ||
759 | SOC_SINGLE("MIC2 Volume", M98088_REG_36_LVL_MIC2, 0, 31, 1), | ||
760 | |||
761 | SOC_SINGLE_EXT_TLV("MIC1 Boost Volume", | ||
762 | M98088_REG_35_LVL_MIC1, 5, 2, 0, | ||
763 | max98088_mic1pre_get, max98088_mic1pre_set, | ||
764 | max98088_micboost_tlv), | ||
765 | SOC_SINGLE_EXT_TLV("MIC2 Boost Volume", | ||
766 | M98088_REG_36_LVL_MIC2, 5, 2, 0, | ||
767 | max98088_mic2pre_get, max98088_mic2pre_set, | ||
768 | max98088_micboost_tlv), | ||
769 | |||
770 | SOC_SINGLE("INA Volume", M98088_REG_37_LVL_INA, 0, 7, 1), | ||
771 | SOC_SINGLE("INB Volume", M98088_REG_38_LVL_INB, 0, 7, 1), | ||
772 | |||
773 | SOC_SINGLE("ADCL Volume", M98088_REG_33_LVL_ADC_L, 0, 15, 0), | ||
774 | SOC_SINGLE("ADCR Volume", M98088_REG_34_LVL_ADC_R, 0, 15, 0), | ||
775 | |||
776 | SOC_SINGLE("ADCL Boost Volume", M98088_REG_33_LVL_ADC_L, 4, 3, 0), | ||
777 | SOC_SINGLE("ADCR Boost Volume", M98088_REG_34_LVL_ADC_R, 4, 3, 0), | ||
778 | |||
779 | SOC_SINGLE("EQ1 Switch", M98088_REG_49_CFG_LEVEL, 0, 1, 0), | ||
780 | SOC_SINGLE("EQ2 Switch", M98088_REG_49_CFG_LEVEL, 1, 1, 0), | ||
781 | |||
782 | SOC_ENUM("EX Limiter Threshold", max98088_ex_thresh_enum), | ||
783 | |||
784 | SOC_ENUM("DAI1 Filter Mode", max98088_filter_mode_enum), | ||
785 | SOC_ENUM("DAI1 DAC Filter", max98088_dai1_dac_filter_enum), | ||
786 | SOC_ENUM("DAI1 ADC Filter", max98088_dai1_adc_filter_enum), | ||
787 | SOC_SINGLE("DAI2 DC Block Switch", M98088_REG_20_DAI2_FILTERS, | ||
788 | 0, 1, 0), | ||
789 | |||
790 | SOC_SINGLE("ALC Switch", M98088_REG_43_SPKALC_COMP, 7, 1, 0), | ||
791 | SOC_SINGLE("ALC Threshold", M98088_REG_43_SPKALC_COMP, 0, 7, 0), | ||
792 | SOC_SINGLE("ALC Multiband", M98088_REG_43_SPKALC_COMP, 3, 1, 0), | ||
793 | SOC_SINGLE("ALC Release Time", M98088_REG_43_SPKALC_COMP, 4, 7, 0), | ||
794 | |||
795 | SOC_SINGLE("PWR Limiter Threshold", M98088_REG_44_PWRLMT_CFG, | ||
796 | 4, 15, 0), | ||
797 | SOC_SINGLE("PWR Limiter Weight", M98088_REG_44_PWRLMT_CFG, 0, 7, 0), | ||
798 | SOC_SINGLE("PWR Limiter Time1", M98088_REG_45_PWRLMT_TIME, 0, 15, 0), | ||
799 | SOC_SINGLE("PWR Limiter Time2", M98088_REG_45_PWRLMT_TIME, 4, 15, 0), | ||
800 | |||
801 | SOC_SINGLE("THD Limiter Threshold", M98088_REG_46_THDLMT_CFG, 4, 15, 0), | ||
802 | SOC_SINGLE("THD Limiter Time", M98088_REG_46_THDLMT_CFG, 0, 7, 0), | ||
803 | }; | ||
804 | |||
805 | /* Left speaker mixer switch */ | ||
806 | static const struct snd_kcontrol_new max98088_left_speaker_mixer_controls[] = { | ||
807 | SOC_DAPM_SINGLE("Left DAC1 Switch", M98088_REG_2B_MIX_SPK_LEFT, 7, 1, 0), | ||
808 | SOC_DAPM_SINGLE("Right DAC1 Switch", M98088_REG_2B_MIX_SPK_LEFT, 0, 1, 0), | ||
809 | SOC_DAPM_SINGLE("Left DAC2 Switch", M98088_REG_2B_MIX_SPK_LEFT, 7, 1, 0), | ||
810 | SOC_DAPM_SINGLE("Right DAC2 Switch", M98088_REG_2B_MIX_SPK_LEFT, 0, 1, 0), | ||
811 | SOC_DAPM_SINGLE("MIC1 Switch", M98088_REG_2B_MIX_SPK_LEFT, 5, 1, 0), | ||
812 | SOC_DAPM_SINGLE("MIC2 Switch", M98088_REG_2B_MIX_SPK_LEFT, 6, 1, 0), | ||
813 | SOC_DAPM_SINGLE("INA1 Switch", M98088_REG_2B_MIX_SPK_LEFT, 1, 1, 0), | ||
814 | SOC_DAPM_SINGLE("INA2 Switch", M98088_REG_2B_MIX_SPK_LEFT, 2, 1, 0), | ||
815 | SOC_DAPM_SINGLE("INB1 Switch", M98088_REG_2B_MIX_SPK_LEFT, 3, 1, 0), | ||
816 | SOC_DAPM_SINGLE("INB2 Switch", M98088_REG_2B_MIX_SPK_LEFT, 4, 1, 0), | ||
817 | }; | ||
818 | |||
819 | /* Right speaker mixer switch */ | ||
820 | static const struct snd_kcontrol_new max98088_right_speaker_mixer_controls[] = { | ||
821 | SOC_DAPM_SINGLE("Left DAC1 Switch", M98088_REG_2C_MIX_SPK_RIGHT, 7, 1, 0), | ||
822 | SOC_DAPM_SINGLE("Right DAC1 Switch", M98088_REG_2C_MIX_SPK_RIGHT, 0, 1, 0), | ||
823 | SOC_DAPM_SINGLE("Left DAC2 Switch", M98088_REG_2C_MIX_SPK_RIGHT, 7, 1, 0), | ||
824 | SOC_DAPM_SINGLE("Right DAC2 Switch", M98088_REG_2C_MIX_SPK_RIGHT, 0, 1, 0), | ||
825 | SOC_DAPM_SINGLE("MIC1 Switch", M98088_REG_2C_MIX_SPK_RIGHT, 5, 1, 0), | ||
826 | SOC_DAPM_SINGLE("MIC2 Switch", M98088_REG_2C_MIX_SPK_RIGHT, 6, 1, 0), | ||
827 | SOC_DAPM_SINGLE("INA1 Switch", M98088_REG_2C_MIX_SPK_RIGHT, 1, 1, 0), | ||
828 | SOC_DAPM_SINGLE("INA2 Switch", M98088_REG_2C_MIX_SPK_RIGHT, 2, 1, 0), | ||
829 | SOC_DAPM_SINGLE("INB1 Switch", M98088_REG_2C_MIX_SPK_RIGHT, 3, 1, 0), | ||
830 | SOC_DAPM_SINGLE("INB2 Switch", M98088_REG_2C_MIX_SPK_RIGHT, 4, 1, 0), | ||
831 | }; | ||
832 | |||
833 | /* Left headphone mixer switch */ | ||
834 | static const struct snd_kcontrol_new max98088_left_hp_mixer_controls[] = { | ||
835 | SOC_DAPM_SINGLE("Left DAC1 Switch", M98088_REG_25_MIX_HP_LEFT, 7, 1, 0), | ||
836 | SOC_DAPM_SINGLE("Right DAC1 Switch", M98088_REG_25_MIX_HP_LEFT, 0, 1, 0), | ||
837 | SOC_DAPM_SINGLE("Left DAC2 Switch", M98088_REG_25_MIX_HP_LEFT, 7, 1, 0), | ||
838 | SOC_DAPM_SINGLE("Right DAC2 Switch", M98088_REG_25_MIX_HP_LEFT, 0, 1, 0), | ||
839 | SOC_DAPM_SINGLE("MIC1 Switch", M98088_REG_25_MIX_HP_LEFT, 5, 1, 0), | ||
840 | SOC_DAPM_SINGLE("MIC2 Switch", M98088_REG_25_MIX_HP_LEFT, 6, 1, 0), | ||
841 | SOC_DAPM_SINGLE("INA1 Switch", M98088_REG_25_MIX_HP_LEFT, 1, 1, 0), | ||
842 | SOC_DAPM_SINGLE("INA2 Switch", M98088_REG_25_MIX_HP_LEFT, 2, 1, 0), | ||
843 | SOC_DAPM_SINGLE("INB1 Switch", M98088_REG_25_MIX_HP_LEFT, 3, 1, 0), | ||
844 | SOC_DAPM_SINGLE("INB2 Switch", M98088_REG_25_MIX_HP_LEFT, 4, 1, 0), | ||
845 | }; | ||
846 | |||
847 | /* Right headphone mixer switch */ | ||
848 | static const struct snd_kcontrol_new max98088_right_hp_mixer_controls[] = { | ||
849 | SOC_DAPM_SINGLE("Left DAC1 Switch", M98088_REG_26_MIX_HP_RIGHT, 7, 1, 0), | ||
850 | SOC_DAPM_SINGLE("Right DAC1 Switch", M98088_REG_26_MIX_HP_RIGHT, 0, 1, 0), | ||
851 | SOC_DAPM_SINGLE("Left DAC2 Switch", M98088_REG_26_MIX_HP_RIGHT, 7, 1, 0), | ||
852 | SOC_DAPM_SINGLE("Right DAC2 Switch", M98088_REG_26_MIX_HP_RIGHT, 0, 1, 0), | ||
853 | SOC_DAPM_SINGLE("MIC1 Switch", M98088_REG_26_MIX_HP_RIGHT, 5, 1, 0), | ||
854 | SOC_DAPM_SINGLE("MIC2 Switch", M98088_REG_26_MIX_HP_RIGHT, 6, 1, 0), | ||
855 | SOC_DAPM_SINGLE("INA1 Switch", M98088_REG_26_MIX_HP_RIGHT, 1, 1, 0), | ||
856 | SOC_DAPM_SINGLE("INA2 Switch", M98088_REG_26_MIX_HP_RIGHT, 2, 1, 0), | ||
857 | SOC_DAPM_SINGLE("INB1 Switch", M98088_REG_26_MIX_HP_RIGHT, 3, 1, 0), | ||
858 | SOC_DAPM_SINGLE("INB2 Switch", M98088_REG_26_MIX_HP_RIGHT, 4, 1, 0), | ||
859 | }; | ||
860 | |||
861 | /* Left earpiece/receiver mixer switch */ | ||
862 | static const struct snd_kcontrol_new max98088_left_rec_mixer_controls[] = { | ||
863 | SOC_DAPM_SINGLE("Left DAC1 Switch", M98088_REG_28_MIX_REC_LEFT, 7, 1, 0), | ||
864 | SOC_DAPM_SINGLE("Right DAC1 Switch", M98088_REG_28_MIX_REC_LEFT, 0, 1, 0), | ||
865 | SOC_DAPM_SINGLE("Left DAC2 Switch", M98088_REG_28_MIX_REC_LEFT, 7, 1, 0), | ||
866 | SOC_DAPM_SINGLE("Right DAC2 Switch", M98088_REG_28_MIX_REC_LEFT, 0, 1, 0), | ||
867 | SOC_DAPM_SINGLE("MIC1 Switch", M98088_REG_28_MIX_REC_LEFT, 5, 1, 0), | ||
868 | SOC_DAPM_SINGLE("MIC2 Switch", M98088_REG_28_MIX_REC_LEFT, 6, 1, 0), | ||
869 | SOC_DAPM_SINGLE("INA1 Switch", M98088_REG_28_MIX_REC_LEFT, 1, 1, 0), | ||
870 | SOC_DAPM_SINGLE("INA2 Switch", M98088_REG_28_MIX_REC_LEFT, 2, 1, 0), | ||
871 | SOC_DAPM_SINGLE("INB1 Switch", M98088_REG_28_MIX_REC_LEFT, 3, 1, 0), | ||
872 | SOC_DAPM_SINGLE("INB2 Switch", M98088_REG_28_MIX_REC_LEFT, 4, 1, 0), | ||
873 | }; | ||
874 | |||
875 | /* Right earpiece/receiver mixer switch */ | ||
876 | static const struct snd_kcontrol_new max98088_right_rec_mixer_controls[] = { | ||
877 | SOC_DAPM_SINGLE("Left DAC1 Switch", M98088_REG_29_MIX_REC_RIGHT, 7, 1, 0), | ||
878 | SOC_DAPM_SINGLE("Right DAC1 Switch", M98088_REG_29_MIX_REC_RIGHT, 0, 1, 0), | ||
879 | SOC_DAPM_SINGLE("Left DAC2 Switch", M98088_REG_29_MIX_REC_RIGHT, 7, 1, 0), | ||
880 | SOC_DAPM_SINGLE("Right DAC2 Switch", M98088_REG_29_MIX_REC_RIGHT, 0, 1, 0), | ||
881 | SOC_DAPM_SINGLE("MIC1 Switch", M98088_REG_29_MIX_REC_RIGHT, 5, 1, 0), | ||
882 | SOC_DAPM_SINGLE("MIC2 Switch", M98088_REG_29_MIX_REC_RIGHT, 6, 1, 0), | ||
883 | SOC_DAPM_SINGLE("INA1 Switch", M98088_REG_29_MIX_REC_RIGHT, 1, 1, 0), | ||
884 | SOC_DAPM_SINGLE("INA2 Switch", M98088_REG_29_MIX_REC_RIGHT, 2, 1, 0), | ||
885 | SOC_DAPM_SINGLE("INB1 Switch", M98088_REG_29_MIX_REC_RIGHT, 3, 1, 0), | ||
886 | SOC_DAPM_SINGLE("INB2 Switch", M98088_REG_29_MIX_REC_RIGHT, 4, 1, 0), | ||
887 | }; | ||
888 | |||
889 | /* Left ADC mixer switch */ | ||
890 | static const struct snd_kcontrol_new max98088_left_ADC_mixer_controls[] = { | ||
891 | SOC_DAPM_SINGLE("MIC1 Switch", M98088_REG_23_MIX_ADC_LEFT, 7, 1, 0), | ||
892 | SOC_DAPM_SINGLE("MIC2 Switch", M98088_REG_23_MIX_ADC_LEFT, 6, 1, 0), | ||
893 | SOC_DAPM_SINGLE("INA1 Switch", M98088_REG_23_MIX_ADC_LEFT, 3, 1, 0), | ||
894 | SOC_DAPM_SINGLE("INA2 Switch", M98088_REG_23_MIX_ADC_LEFT, 2, 1, 0), | ||
895 | SOC_DAPM_SINGLE("INB1 Switch", M98088_REG_23_MIX_ADC_LEFT, 1, 1, 0), | ||
896 | SOC_DAPM_SINGLE("INB2 Switch", M98088_REG_23_MIX_ADC_LEFT, 0, 1, 0), | ||
897 | }; | ||
898 | |||
899 | /* Right ADC mixer switch */ | ||
900 | static const struct snd_kcontrol_new max98088_right_ADC_mixer_controls[] = { | ||
901 | SOC_DAPM_SINGLE("MIC1 Switch", M98088_REG_24_MIX_ADC_RIGHT, 7, 1, 0), | ||
902 | SOC_DAPM_SINGLE("MIC2 Switch", M98088_REG_24_MIX_ADC_RIGHT, 6, 1, 0), | ||
903 | SOC_DAPM_SINGLE("INA1 Switch", M98088_REG_24_MIX_ADC_RIGHT, 3, 1, 0), | ||
904 | SOC_DAPM_SINGLE("INA2 Switch", M98088_REG_24_MIX_ADC_RIGHT, 2, 1, 0), | ||
905 | SOC_DAPM_SINGLE("INB1 Switch", M98088_REG_24_MIX_ADC_RIGHT, 1, 1, 0), | ||
906 | SOC_DAPM_SINGLE("INB2 Switch", M98088_REG_24_MIX_ADC_RIGHT, 0, 1, 0), | ||
907 | }; | ||
908 | |||
909 | static int max98088_mic_event(struct snd_soc_dapm_widget *w, | ||
910 | struct snd_kcontrol *kcontrol, int event) | ||
911 | { | ||
912 | struct snd_soc_codec *codec = w->codec; | ||
913 | struct max98088_priv *max98088 = snd_soc_codec_get_drvdata(codec); | ||
914 | |||
915 | switch (event) { | ||
916 | case SND_SOC_DAPM_POST_PMU: | ||
917 | if (w->reg == M98088_REG_35_LVL_MIC1) { | ||
918 | snd_soc_update_bits(codec, w->reg, M98088_MICPRE_MASK, | ||
919 | (1+max98088->mic1pre)<<M98088_MICPRE_SHIFT); | ||
920 | } else { | ||
921 | snd_soc_update_bits(codec, w->reg, M98088_MICPRE_MASK, | ||
922 | (1+max98088->mic2pre)<<M98088_MICPRE_SHIFT); | ||
923 | } | ||
924 | break; | ||
925 | case SND_SOC_DAPM_POST_PMD: | ||
926 | snd_soc_update_bits(codec, w->reg, M98088_MICPRE_MASK, 0); | ||
927 | break; | ||
928 | default: | ||
929 | return -EINVAL; | ||
930 | } | ||
931 | |||
932 | return 0; | ||
933 | } | ||
934 | |||
935 | /* | ||
936 | * The line inputs are 2-channel stereo inputs with the left | ||
937 | * and right channels sharing a common PGA power control signal. | ||
938 | */ | ||
939 | static int max98088_line_pga(struct snd_soc_dapm_widget *w, | ||
940 | int event, int line, u8 channel) | ||
941 | { | ||
942 | struct snd_soc_codec *codec = w->codec; | ||
943 | struct max98088_priv *max98088 = snd_soc_codec_get_drvdata(codec); | ||
944 | u8 *state; | ||
945 | |||
946 | BUG_ON(!((channel == 1) || (channel == 2))); | ||
947 | |||
948 | switch (line) { | ||
949 | case LINE_INA: | ||
950 | state = &max98088->ina_state; | ||
951 | break; | ||
952 | case LINE_INB: | ||
953 | state = &max98088->inb_state; | ||
954 | break; | ||
955 | default: | ||
956 | return -EINVAL; | ||
957 | } | ||
958 | |||
959 | switch (event) { | ||
960 | case SND_SOC_DAPM_POST_PMU: | ||
961 | *state |= channel; | ||
962 | snd_soc_update_bits(codec, w->reg, | ||
963 | (1 << w->shift), (1 << w->shift)); | ||
964 | break; | ||
965 | case SND_SOC_DAPM_POST_PMD: | ||
966 | *state &= ~channel; | ||
967 | if (*state == 0) { | ||
968 | snd_soc_update_bits(codec, w->reg, | ||
969 | (1 << w->shift), 0); | ||
970 | } | ||
971 | break; | ||
972 | default: | ||
973 | return -EINVAL; | ||
974 | } | ||
975 | |||
976 | return 0; | ||
977 | } | ||
978 | |||
979 | static int max98088_pga_ina1_event(struct snd_soc_dapm_widget *w, | ||
980 | struct snd_kcontrol *k, int event) | ||
981 | { | ||
982 | return max98088_line_pga(w, event, LINE_INA, 1); | ||
983 | } | ||
984 | |||
985 | static int max98088_pga_ina2_event(struct snd_soc_dapm_widget *w, | ||
986 | struct snd_kcontrol *k, int event) | ||
987 | { | ||
988 | return max98088_line_pga(w, event, LINE_INA, 2); | ||
989 | } | ||
990 | |||
991 | static int max98088_pga_inb1_event(struct snd_soc_dapm_widget *w, | ||
992 | struct snd_kcontrol *k, int event) | ||
993 | { | ||
994 | return max98088_line_pga(w, event, LINE_INB, 1); | ||
995 | } | ||
996 | |||
997 | static int max98088_pga_inb2_event(struct snd_soc_dapm_widget *w, | ||
998 | struct snd_kcontrol *k, int event) | ||
999 | { | ||
1000 | return max98088_line_pga(w, event, LINE_INB, 2); | ||
1001 | } | ||
1002 | |||
1003 | static const struct snd_soc_dapm_widget max98088_dapm_widgets[] = { | ||
1004 | |||
1005 | SND_SOC_DAPM_ADC("ADCL", "HiFi Capture", M98088_REG_4C_PWR_EN_IN, 1, 0), | ||
1006 | SND_SOC_DAPM_ADC("ADCR", "HiFi Capture", M98088_REG_4C_PWR_EN_IN, 0, 0), | ||
1007 | |||
1008 | SND_SOC_DAPM_DAC("DACL1", "HiFi Playback", | ||
1009 | M98088_REG_4D_PWR_EN_OUT, 1, 0), | ||
1010 | SND_SOC_DAPM_DAC("DACR1", "HiFi Playback", | ||
1011 | M98088_REG_4D_PWR_EN_OUT, 0, 0), | ||
1012 | SND_SOC_DAPM_DAC("DACL2", "Aux Playback", | ||
1013 | M98088_REG_4D_PWR_EN_OUT, 1, 0), | ||
1014 | SND_SOC_DAPM_DAC("DACR2", "Aux Playback", | ||
1015 | M98088_REG_4D_PWR_EN_OUT, 0, 0), | ||
1016 | |||
1017 | SND_SOC_DAPM_PGA("HP Left Out", M98088_REG_4D_PWR_EN_OUT, | ||
1018 | 7, 0, NULL, 0), | ||
1019 | SND_SOC_DAPM_PGA("HP Right Out", M98088_REG_4D_PWR_EN_OUT, | ||
1020 | 6, 0, NULL, 0), | ||
1021 | |||
1022 | SND_SOC_DAPM_PGA("SPK Left Out", M98088_REG_4D_PWR_EN_OUT, | ||
1023 | 5, 0, NULL, 0), | ||
1024 | SND_SOC_DAPM_PGA("SPK Right Out", M98088_REG_4D_PWR_EN_OUT, | ||
1025 | 4, 0, NULL, 0), | ||
1026 | |||
1027 | SND_SOC_DAPM_PGA("REC Left Out", M98088_REG_4D_PWR_EN_OUT, | ||
1028 | 3, 0, NULL, 0), | ||
1029 | SND_SOC_DAPM_PGA("REC Right Out", M98088_REG_4D_PWR_EN_OUT, | ||
1030 | 2, 0, NULL, 0), | ||
1031 | |||
1032 | SND_SOC_DAPM_MUX("External MIC", SND_SOC_NOPM, 0, 0, | ||
1033 | &max98088_extmic_mux), | ||
1034 | |||
1035 | SND_SOC_DAPM_MIXER("Left HP Mixer", SND_SOC_NOPM, 0, 0, | ||
1036 | &max98088_left_hp_mixer_controls[0], | ||
1037 | ARRAY_SIZE(max98088_left_hp_mixer_controls)), | ||
1038 | |||
1039 | SND_SOC_DAPM_MIXER("Right HP Mixer", SND_SOC_NOPM, 0, 0, | ||
1040 | &max98088_right_hp_mixer_controls[0], | ||
1041 | ARRAY_SIZE(max98088_right_hp_mixer_controls)), | ||
1042 | |||
1043 | SND_SOC_DAPM_MIXER("Left SPK Mixer", SND_SOC_NOPM, 0, 0, | ||
1044 | &max98088_left_speaker_mixer_controls[0], | ||
1045 | ARRAY_SIZE(max98088_left_speaker_mixer_controls)), | ||
1046 | |||
1047 | SND_SOC_DAPM_MIXER("Right SPK Mixer", SND_SOC_NOPM, 0, 0, | ||
1048 | &max98088_right_speaker_mixer_controls[0], | ||
1049 | ARRAY_SIZE(max98088_right_speaker_mixer_controls)), | ||
1050 | |||
1051 | SND_SOC_DAPM_MIXER("Left REC Mixer", SND_SOC_NOPM, 0, 0, | ||
1052 | &max98088_left_rec_mixer_controls[0], | ||
1053 | ARRAY_SIZE(max98088_left_rec_mixer_controls)), | ||
1054 | |||
1055 | SND_SOC_DAPM_MIXER("Right REC Mixer", SND_SOC_NOPM, 0, 0, | ||
1056 | &max98088_right_rec_mixer_controls[0], | ||
1057 | ARRAY_SIZE(max98088_right_rec_mixer_controls)), | ||
1058 | |||
1059 | SND_SOC_DAPM_MIXER("Left ADC Mixer", SND_SOC_NOPM, 0, 0, | ||
1060 | &max98088_left_ADC_mixer_controls[0], | ||
1061 | ARRAY_SIZE(max98088_left_ADC_mixer_controls)), | ||
1062 | |||
1063 | SND_SOC_DAPM_MIXER("Right ADC Mixer", SND_SOC_NOPM, 0, 0, | ||
1064 | &max98088_right_ADC_mixer_controls[0], | ||
1065 | ARRAY_SIZE(max98088_right_ADC_mixer_controls)), | ||
1066 | |||
1067 | SND_SOC_DAPM_PGA_E("MIC1 Input", M98088_REG_35_LVL_MIC1, | ||
1068 | 5, 0, NULL, 0, max98088_mic_event, | ||
1069 | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), | ||
1070 | |||
1071 | SND_SOC_DAPM_PGA_E("MIC2 Input", M98088_REG_36_LVL_MIC2, | ||
1072 | 5, 0, NULL, 0, max98088_mic_event, | ||
1073 | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), | ||
1074 | |||
1075 | SND_SOC_DAPM_PGA_E("INA1 Input", M98088_REG_4C_PWR_EN_IN, | ||
1076 | 7, 0, NULL, 0, max98088_pga_ina1_event, | ||
1077 | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), | ||
1078 | |||
1079 | SND_SOC_DAPM_PGA_E("INA2 Input", M98088_REG_4C_PWR_EN_IN, | ||
1080 | 7, 0, NULL, 0, max98088_pga_ina2_event, | ||
1081 | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), | ||
1082 | |||
1083 | SND_SOC_DAPM_PGA_E("INB1 Input", M98088_REG_4C_PWR_EN_IN, | ||
1084 | 6, 0, NULL, 0, max98088_pga_inb1_event, | ||
1085 | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), | ||
1086 | |||
1087 | SND_SOC_DAPM_PGA_E("INB2 Input", M98088_REG_4C_PWR_EN_IN, | ||
1088 | 6, 0, NULL, 0, max98088_pga_inb2_event, | ||
1089 | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), | ||
1090 | |||
1091 | SND_SOC_DAPM_MICBIAS("MICBIAS", M98088_REG_4C_PWR_EN_IN, 3, 0), | ||
1092 | |||
1093 | SND_SOC_DAPM_MUX("EX Limiter Mode", SND_SOC_NOPM, 0, 0, | ||
1094 | &max98088_exmode_controls), | ||
1095 | |||
1096 | SND_SOC_DAPM_OUTPUT("HPL"), | ||
1097 | SND_SOC_DAPM_OUTPUT("HPR"), | ||
1098 | SND_SOC_DAPM_OUTPUT("SPKL"), | ||
1099 | SND_SOC_DAPM_OUTPUT("SPKR"), | ||
1100 | SND_SOC_DAPM_OUTPUT("RECL"), | ||
1101 | SND_SOC_DAPM_OUTPUT("RECR"), | ||
1102 | |||
1103 | SND_SOC_DAPM_INPUT("MIC1"), | ||
1104 | SND_SOC_DAPM_INPUT("MIC2"), | ||
1105 | SND_SOC_DAPM_INPUT("INA1"), | ||
1106 | SND_SOC_DAPM_INPUT("INA2"), | ||
1107 | SND_SOC_DAPM_INPUT("INB1"), | ||
1108 | SND_SOC_DAPM_INPUT("INB2"), | ||
1109 | }; | ||
1110 | |||
1111 | static const struct snd_soc_dapm_route audio_map[] = { | ||
1112 | /* Left headphone output mixer */ | ||
1113 | {"Left HP Mixer", "Left DAC1 Switch", "DACL1"}, | ||
1114 | {"Left HP Mixer", "Left DAC2 Switch", "DACL2"}, | ||
1115 | {"Left HP Mixer", "Right DAC1 Switch", "DACR1"}, | ||
1116 | {"Left HP Mixer", "Right DAC2 Switch", "DACR2"}, | ||
1117 | {"Left HP Mixer", "MIC1 Switch", "MIC1 Input"}, | ||
1118 | {"Left HP Mixer", "MIC2 Switch", "MIC2 Input"}, | ||
1119 | {"Left HP Mixer", "INA1 Switch", "INA1 Input"}, | ||
1120 | {"Left HP Mixer", "INA2 Switch", "INA2 Input"}, | ||
1121 | {"Left HP Mixer", "INB1 Switch", "INB1 Input"}, | ||
1122 | {"Left HP Mixer", "INB2 Switch", "INB2 Input"}, | ||
1123 | |||
1124 | /* Right headphone output mixer */ | ||
1125 | {"Right HP Mixer", "Left DAC1 Switch", "DACL1"}, | ||
1126 | {"Right HP Mixer", "Left DAC2 Switch", "DACL2" }, | ||
1127 | {"Right HP Mixer", "Right DAC1 Switch", "DACR1"}, | ||
1128 | {"Right HP Mixer", "Right DAC2 Switch", "DACR2"}, | ||
1129 | {"Right HP Mixer", "MIC1 Switch", "MIC1 Input"}, | ||
1130 | {"Right HP Mixer", "MIC2 Switch", "MIC2 Input"}, | ||
1131 | {"Right HP Mixer", "INA1 Switch", "INA1 Input"}, | ||
1132 | {"Right HP Mixer", "INA2 Switch", "INA2 Input"}, | ||
1133 | {"Right HP Mixer", "INB1 Switch", "INB1 Input"}, | ||
1134 | {"Right HP Mixer", "INB2 Switch", "INB2 Input"}, | ||
1135 | |||
1136 | /* Left speaker output mixer */ | ||
1137 | {"Left SPK Mixer", "Left DAC1 Switch", "DACL1"}, | ||
1138 | {"Left SPK Mixer", "Left DAC2 Switch", "DACL2"}, | ||
1139 | {"Left SPK Mixer", "Right DAC1 Switch", "DACR1"}, | ||
1140 | {"Left SPK Mixer", "Right DAC2 Switch", "DACR2"}, | ||
1141 | {"Left SPK Mixer", "MIC1 Switch", "MIC1 Input"}, | ||
1142 | {"Left SPK Mixer", "MIC2 Switch", "MIC2 Input"}, | ||
1143 | {"Left SPK Mixer", "INA1 Switch", "INA1 Input"}, | ||
1144 | {"Left SPK Mixer", "INA2 Switch", "INA2 Input"}, | ||
1145 | {"Left SPK Mixer", "INB1 Switch", "INB1 Input"}, | ||
1146 | {"Left SPK Mixer", "INB2 Switch", "INB2 Input"}, | ||
1147 | |||
1148 | /* Right speaker output mixer */ | ||
1149 | {"Right SPK Mixer", "Left DAC1 Switch", "DACL1"}, | ||
1150 | {"Right SPK Mixer", "Left DAC2 Switch", "DACL2"}, | ||
1151 | {"Right SPK Mixer", "Right DAC1 Switch", "DACR1"}, | ||
1152 | {"Right SPK Mixer", "Right DAC2 Switch", "DACR2"}, | ||
1153 | {"Right SPK Mixer", "MIC1 Switch", "MIC1 Input"}, | ||
1154 | {"Right SPK Mixer", "MIC2 Switch", "MIC2 Input"}, | ||
1155 | {"Right SPK Mixer", "INA1 Switch", "INA1 Input"}, | ||
1156 | {"Right SPK Mixer", "INA2 Switch", "INA2 Input"}, | ||
1157 | {"Right SPK Mixer", "INB1 Switch", "INB1 Input"}, | ||
1158 | {"Right SPK Mixer", "INB2 Switch", "INB2 Input"}, | ||
1159 | |||
1160 | /* Earpiece/Receiver output mixer */ | ||
1161 | {"Left REC Mixer", "Left DAC1 Switch", "DACL1"}, | ||
1162 | {"Left REC Mixer", "Left DAC2 Switch", "DACL2"}, | ||
1163 | {"Left REC Mixer", "Right DAC1 Switch", "DACR1"}, | ||
1164 | {"Left REC Mixer", "Right DAC2 Switch", "DACR2"}, | ||
1165 | {"Left REC Mixer", "MIC1 Switch", "MIC1 Input"}, | ||
1166 | {"Left REC Mixer", "MIC2 Switch", "MIC2 Input"}, | ||
1167 | {"Left REC Mixer", "INA1 Switch", "INA1 Input"}, | ||
1168 | {"Left REC Mixer", "INA2 Switch", "INA2 Input"}, | ||
1169 | {"Left REC Mixer", "INB1 Switch", "INB1 Input"}, | ||
1170 | {"Left REC Mixer", "INB2 Switch", "INB2 Input"}, | ||
1171 | |||
1172 | /* Earpiece/Receiver output mixer */ | ||
1173 | {"Right REC Mixer", "Left DAC1 Switch", "DACL1"}, | ||
1174 | {"Right REC Mixer", "Left DAC2 Switch", "DACL2"}, | ||
1175 | {"Right REC Mixer", "Right DAC1 Switch", "DACR1"}, | ||
1176 | {"Right REC Mixer", "Right DAC2 Switch", "DACR2"}, | ||
1177 | {"Right REC Mixer", "MIC1 Switch", "MIC1 Input"}, | ||
1178 | {"Right REC Mixer", "MIC2 Switch", "MIC2 Input"}, | ||
1179 | {"Right REC Mixer", "INA1 Switch", "INA1 Input"}, | ||
1180 | {"Right REC Mixer", "INA2 Switch", "INA2 Input"}, | ||
1181 | {"Right REC Mixer", "INB1 Switch", "INB1 Input"}, | ||
1182 | {"Right REC Mixer", "INB2 Switch", "INB2 Input"}, | ||
1183 | |||
1184 | {"HP Left Out", NULL, "Left HP Mixer"}, | ||
1185 | {"HP Right Out", NULL, "Right HP Mixer"}, | ||
1186 | {"SPK Left Out", NULL, "Left SPK Mixer"}, | ||
1187 | {"SPK Right Out", NULL, "Right SPK Mixer"}, | ||
1188 | {"REC Left Out", NULL, "Left REC Mixer"}, | ||
1189 | {"REC Right Out", NULL, "Right REC Mixer"}, | ||
1190 | |||
1191 | {"HPL", NULL, "HP Left Out"}, | ||
1192 | {"HPR", NULL, "HP Right Out"}, | ||
1193 | {"SPKL", NULL, "SPK Left Out"}, | ||
1194 | {"SPKR", NULL, "SPK Right Out"}, | ||
1195 | {"RECL", NULL, "REC Left Out"}, | ||
1196 | {"RECR", NULL, "REC Right Out"}, | ||
1197 | |||
1198 | /* Left ADC input mixer */ | ||
1199 | {"Left ADC Mixer", "MIC1 Switch", "MIC1 Input"}, | ||
1200 | {"Left ADC Mixer", "MIC2 Switch", "MIC2 Input"}, | ||
1201 | {"Left ADC Mixer", "INA1 Switch", "INA1 Input"}, | ||
1202 | {"Left ADC Mixer", "INA2 Switch", "INA2 Input"}, | ||
1203 | {"Left ADC Mixer", "INB1 Switch", "INB1 Input"}, | ||
1204 | {"Left ADC Mixer", "INB2 Switch", "INB2 Input"}, | ||
1205 | |||
1206 | /* Right ADC input mixer */ | ||
1207 | {"Right ADC Mixer", "MIC1 Switch", "MIC1 Input"}, | ||
1208 | {"Right ADC Mixer", "MIC2 Switch", "MIC2 Input"}, | ||
1209 | {"Right ADC Mixer", "INA1 Switch", "INA1 Input"}, | ||
1210 | {"Right ADC Mixer", "INA2 Switch", "INA2 Input"}, | ||
1211 | {"Right ADC Mixer", "INB1 Switch", "INB1 Input"}, | ||
1212 | {"Right ADC Mixer", "INB2 Switch", "INB2 Input"}, | ||
1213 | |||
1214 | /* Inputs */ | ||
1215 | {"ADCL", NULL, "Left ADC Mixer"}, | ||
1216 | {"ADCR", NULL, "Right ADC Mixer"}, | ||
1217 | {"INA1 Input", NULL, "INA1"}, | ||
1218 | {"INA2 Input", NULL, "INA2"}, | ||
1219 | {"INB1 Input", NULL, "INB1"}, | ||
1220 | {"INB2 Input", NULL, "INB2"}, | ||
1221 | {"MIC1 Input", NULL, "MIC1"}, | ||
1222 | {"MIC2 Input", NULL, "MIC2"}, | ||
1223 | }; | ||
1224 | |||
1225 | static int max98088_add_widgets(struct snd_soc_codec *codec) | ||
1226 | { | ||
1227 | snd_soc_dapm_new_controls(codec, max98088_dapm_widgets, | ||
1228 | ARRAY_SIZE(max98088_dapm_widgets)); | ||
1229 | |||
1230 | snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map)); | ||
1231 | |||
1232 | snd_soc_add_controls(codec, max98088_snd_controls, | ||
1233 | ARRAY_SIZE(max98088_snd_controls)); | ||
1234 | |||
1235 | snd_soc_dapm_new_widgets(codec); | ||
1236 | return 0; | ||
1237 | } | ||
1238 | |||
1239 | /* codec mclk clock divider coefficients */ | ||
1240 | static const struct { | ||
1241 | u32 rate; | ||
1242 | u8 sr; | ||
1243 | } rate_table[] = { | ||
1244 | {8000, 0x10}, | ||
1245 | {11025, 0x20}, | ||
1246 | {16000, 0x30}, | ||
1247 | {22050, 0x40}, | ||
1248 | {24000, 0x50}, | ||
1249 | {32000, 0x60}, | ||
1250 | {44100, 0x70}, | ||
1251 | {48000, 0x80}, | ||
1252 | {88200, 0x90}, | ||
1253 | {96000, 0xA0}, | ||
1254 | }; | ||
1255 | |||
1256 | static inline int rate_value(int rate, u8 *value) | ||
1257 | { | ||
1258 | int i; | ||
1259 | |||
1260 | for (i = 0; i < ARRAY_SIZE(rate_table); i++) { | ||
1261 | if (rate_table[i].rate >= rate) { | ||
1262 | *value = rate_table[i].sr; | ||
1263 | return 0; | ||
1264 | } | ||
1265 | } | ||
1266 | *value = rate_table[0].sr; | ||
1267 | return -EINVAL; | ||
1268 | } | ||
1269 | |||
1270 | static int max98088_dai1_hw_params(struct snd_pcm_substream *substream, | ||
1271 | struct snd_pcm_hw_params *params, | ||
1272 | struct snd_soc_dai *dai) | ||
1273 | { | ||
1274 | struct snd_soc_codec *codec = dai->codec; | ||
1275 | struct max98088_priv *max98088 = snd_soc_codec_get_drvdata(codec); | ||
1276 | struct max98088_cdata *cdata; | ||
1277 | unsigned long long ni; | ||
1278 | unsigned int rate; | ||
1279 | u8 regval; | ||
1280 | |||
1281 | cdata = &max98088->dai[0]; | ||
1282 | |||
1283 | rate = params_rate(params); | ||
1284 | |||
1285 | switch (params_format(params)) { | ||
1286 | case SNDRV_PCM_FORMAT_S16_LE: | ||
1287 | snd_soc_update_bits(codec, M98088_REG_14_DAI1_FORMAT, | ||
1288 | M98088_DAI_WS, 0); | ||
1289 | break; | ||
1290 | case SNDRV_PCM_FORMAT_S24_LE: | ||
1291 | snd_soc_update_bits(codec, M98088_REG_14_DAI1_FORMAT, | ||
1292 | M98088_DAI_WS, M98088_DAI_WS); | ||
1293 | break; | ||
1294 | default: | ||
1295 | return -EINVAL; | ||
1296 | } | ||
1297 | |||
1298 | snd_soc_update_bits(codec, M98088_REG_51_PWR_SYS, M98088_SHDNRUN, 0); | ||
1299 | |||
1300 | if (rate_value(rate, ®val)) | ||
1301 | return -EINVAL; | ||
1302 | |||
1303 | snd_soc_update_bits(codec, M98088_REG_11_DAI1_CLKMODE, | ||
1304 | M98088_CLKMODE_MASK, regval); | ||
1305 | cdata->rate = rate; | ||
1306 | |||
1307 | /* Configure NI when operating as master */ | ||
1308 | if (snd_soc_read(codec, M98088_REG_14_DAI1_FORMAT) | ||
1309 | & M98088_DAI_MAS) { | ||
1310 | if (max98088->sysclk == 0) { | ||
1311 | dev_err(codec->dev, "Invalid system clock frequency\n"); | ||
1312 | return -EINVAL; | ||
1313 | } | ||
1314 | ni = 65536ULL * (rate < 50000 ? 96ULL : 48ULL) | ||
1315 | * (unsigned long long int)rate; | ||
1316 | do_div(ni, (unsigned long long int)max98088->sysclk); | ||
1317 | snd_soc_write(codec, M98088_REG_12_DAI1_CLKCFG_HI, | ||
1318 | (ni >> 8) & 0x7F); | ||
1319 | snd_soc_write(codec, M98088_REG_13_DAI1_CLKCFG_LO, | ||
1320 | ni & 0xFF); | ||
1321 | } | ||
1322 | |||
1323 | /* Update sample rate mode */ | ||
1324 | if (rate < 50000) | ||
1325 | snd_soc_update_bits(codec, M98088_REG_18_DAI1_FILTERS, | ||
1326 | M98088_DAI_DHF, 0); | ||
1327 | else | ||
1328 | snd_soc_update_bits(codec, M98088_REG_18_DAI1_FILTERS, | ||
1329 | M98088_DAI_DHF, M98088_DAI_DHF); | ||
1330 | |||
1331 | snd_soc_update_bits(codec, M98088_REG_51_PWR_SYS, M98088_SHDNRUN, | ||
1332 | M98088_SHDNRUN); | ||
1333 | |||
1334 | return 0; | ||
1335 | } | ||
1336 | |||
1337 | static int max98088_dai2_hw_params(struct snd_pcm_substream *substream, | ||
1338 | struct snd_pcm_hw_params *params, | ||
1339 | struct snd_soc_dai *dai) | ||
1340 | { | ||
1341 | struct snd_soc_codec *codec = dai->codec; | ||
1342 | struct max98088_priv *max98088 = snd_soc_codec_get_drvdata(codec); | ||
1343 | struct max98088_cdata *cdata; | ||
1344 | unsigned long long ni; | ||
1345 | unsigned int rate; | ||
1346 | u8 regval; | ||
1347 | |||
1348 | cdata = &max98088->dai[1]; | ||
1349 | |||
1350 | rate = params_rate(params); | ||
1351 | |||
1352 | switch (params_format(params)) { | ||
1353 | case SNDRV_PCM_FORMAT_S16_LE: | ||
1354 | snd_soc_update_bits(codec, M98088_REG_1C_DAI2_FORMAT, | ||
1355 | M98088_DAI_WS, 0); | ||
1356 | break; | ||
1357 | case SNDRV_PCM_FORMAT_S24_LE: | ||
1358 | snd_soc_update_bits(codec, M98088_REG_1C_DAI2_FORMAT, | ||
1359 | M98088_DAI_WS, M98088_DAI_WS); | ||
1360 | break; | ||
1361 | default: | ||
1362 | return -EINVAL; | ||
1363 | } | ||
1364 | |||
1365 | snd_soc_update_bits(codec, M98088_REG_51_PWR_SYS, M98088_SHDNRUN, 0); | ||
1366 | |||
1367 | if (rate_value(rate, ®val)) | ||
1368 | return -EINVAL; | ||
1369 | |||
1370 | snd_soc_update_bits(codec, M98088_REG_19_DAI2_CLKMODE, | ||
1371 | M98088_CLKMODE_MASK, regval); | ||
1372 | cdata->rate = rate; | ||
1373 | |||
1374 | /* Configure NI when operating as master */ | ||
1375 | if (snd_soc_read(codec, M98088_REG_1C_DAI2_FORMAT) | ||
1376 | & M98088_DAI_MAS) { | ||
1377 | if (max98088->sysclk == 0) { | ||
1378 | dev_err(codec->dev, "Invalid system clock frequency\n"); | ||
1379 | return -EINVAL; | ||
1380 | } | ||
1381 | ni = 65536ULL * (rate < 50000 ? 96ULL : 48ULL) | ||
1382 | * (unsigned long long int)rate; | ||
1383 | do_div(ni, (unsigned long long int)max98088->sysclk); | ||
1384 | snd_soc_write(codec, M98088_REG_1A_DAI2_CLKCFG_HI, | ||
1385 | (ni >> 8) & 0x7F); | ||
1386 | snd_soc_write(codec, M98088_REG_1B_DAI2_CLKCFG_LO, | ||
1387 | ni & 0xFF); | ||
1388 | } | ||
1389 | |||
1390 | /* Update sample rate mode */ | ||
1391 | if (rate < 50000) | ||
1392 | snd_soc_update_bits(codec, M98088_REG_20_DAI2_FILTERS, | ||
1393 | M98088_DAI_DHF, 0); | ||
1394 | else | ||
1395 | snd_soc_update_bits(codec, M98088_REG_20_DAI2_FILTERS, | ||
1396 | M98088_DAI_DHF, M98088_DAI_DHF); | ||
1397 | |||
1398 | snd_soc_update_bits(codec, M98088_REG_51_PWR_SYS, M98088_SHDNRUN, | ||
1399 | M98088_SHDNRUN); | ||
1400 | |||
1401 | return 0; | ||
1402 | } | ||
1403 | |||
1404 | static int max98088_dai_set_sysclk(struct snd_soc_dai *dai, | ||
1405 | int clk_id, unsigned int freq, int dir) | ||
1406 | { | ||
1407 | struct snd_soc_codec *codec = dai->codec; | ||
1408 | struct max98088_priv *max98088 = snd_soc_codec_get_drvdata(codec); | ||
1409 | |||
1410 | /* Requested clock frequency is already setup */ | ||
1411 | if (freq == max98088->sysclk) | ||
1412 | return 0; | ||
1413 | |||
1414 | max98088->sysclk = freq; /* remember current sysclk */ | ||
1415 | |||
1416 | /* Setup clocks for slave mode, and using the PLL | ||
1417 | * PSCLK = 0x01 (when master clk is 10MHz to 20MHz) | ||
1418 | * 0x02 (when master clk is 20MHz to 30MHz).. | ||
1419 | */ | ||
1420 | if ((freq >= 10000000) && (freq < 20000000)) { | ||
1421 | snd_soc_write(codec, M98088_REG_10_SYS_CLK, 0x10); | ||
1422 | } else if ((freq >= 20000000) && (freq < 30000000)) { | ||
1423 | snd_soc_write(codec, M98088_REG_10_SYS_CLK, 0x20); | ||
1424 | } else { | ||
1425 | dev_err(codec->dev, "Invalid master clock frequency\n"); | ||
1426 | return -EINVAL; | ||
1427 | } | ||
1428 | |||
1429 | if (snd_soc_read(codec, M98088_REG_51_PWR_SYS) & M98088_SHDNRUN) { | ||
1430 | snd_soc_update_bits(codec, M98088_REG_51_PWR_SYS, | ||
1431 | M98088_SHDNRUN, 0); | ||
1432 | snd_soc_update_bits(codec, M98088_REG_51_PWR_SYS, | ||
1433 | M98088_SHDNRUN, M98088_SHDNRUN); | ||
1434 | } | ||
1435 | |||
1436 | dev_dbg(dai->dev, "Clock source is %d at %uHz\n", clk_id, freq); | ||
1437 | |||
1438 | max98088->sysclk = freq; | ||
1439 | return 0; | ||
1440 | } | ||
1441 | |||
1442 | static int max98088_dai1_set_fmt(struct snd_soc_dai *codec_dai, | ||
1443 | unsigned int fmt) | ||
1444 | { | ||
1445 | struct snd_soc_codec *codec = codec_dai->codec; | ||
1446 | struct max98088_priv *max98088 = snd_soc_codec_get_drvdata(codec); | ||
1447 | struct max98088_cdata *cdata; | ||
1448 | u8 reg15val; | ||
1449 | u8 reg14val = 0; | ||
1450 | |||
1451 | cdata = &max98088->dai[0]; | ||
1452 | |||
1453 | if (fmt != cdata->fmt) { | ||
1454 | cdata->fmt = fmt; | ||
1455 | |||
1456 | switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { | ||
1457 | case SND_SOC_DAIFMT_CBS_CFS: | ||
1458 | /* Slave mode PLL */ | ||
1459 | snd_soc_write(codec, M98088_REG_12_DAI1_CLKCFG_HI, | ||
1460 | 0x80); | ||
1461 | snd_soc_write(codec, M98088_REG_13_DAI1_CLKCFG_LO, | ||
1462 | 0x00); | ||
1463 | break; | ||
1464 | case SND_SOC_DAIFMT_CBM_CFM: | ||
1465 | /* Set to master mode */ | ||
1466 | reg14val |= M98088_DAI_MAS; | ||
1467 | break; | ||
1468 | case SND_SOC_DAIFMT_CBS_CFM: | ||
1469 | case SND_SOC_DAIFMT_CBM_CFS: | ||
1470 | default: | ||
1471 | dev_err(codec->dev, "Clock mode unsupported"); | ||
1472 | return -EINVAL; | ||
1473 | } | ||
1474 | |||
1475 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { | ||
1476 | case SND_SOC_DAIFMT_I2S: | ||
1477 | reg14val |= M98088_DAI_DLY; | ||
1478 | break; | ||
1479 | case SND_SOC_DAIFMT_LEFT_J: | ||
1480 | break; | ||
1481 | default: | ||
1482 | return -EINVAL; | ||
1483 | } | ||
1484 | |||
1485 | switch (fmt & SND_SOC_DAIFMT_INV_MASK) { | ||
1486 | case SND_SOC_DAIFMT_NB_NF: | ||
1487 | break; | ||
1488 | case SND_SOC_DAIFMT_NB_IF: | ||
1489 | reg14val |= M98088_DAI_WCI; | ||
1490 | break; | ||
1491 | case SND_SOC_DAIFMT_IB_NF: | ||
1492 | reg14val |= M98088_DAI_BCI; | ||
1493 | break; | ||
1494 | case SND_SOC_DAIFMT_IB_IF: | ||
1495 | reg14val |= M98088_DAI_BCI|M98088_DAI_WCI; | ||
1496 | break; | ||
1497 | default: | ||
1498 | return -EINVAL; | ||
1499 | } | ||
1500 | |||
1501 | snd_soc_update_bits(codec, M98088_REG_14_DAI1_FORMAT, | ||
1502 | M98088_DAI_MAS | M98088_DAI_DLY | M98088_DAI_BCI | | ||
1503 | M98088_DAI_WCI, reg14val); | ||
1504 | |||
1505 | reg15val = M98088_DAI_BSEL64; | ||
1506 | if (max98088->digmic) | ||
1507 | reg15val |= M98088_DAI_OSR64; | ||
1508 | snd_soc_write(codec, M98088_REG_15_DAI1_CLOCK, reg15val); | ||
1509 | } | ||
1510 | |||
1511 | return 0; | ||
1512 | } | ||
1513 | |||
1514 | static int max98088_dai2_set_fmt(struct snd_soc_dai *codec_dai, | ||
1515 | unsigned int fmt) | ||
1516 | { | ||
1517 | struct snd_soc_codec *codec = codec_dai->codec; | ||
1518 | struct max98088_priv *max98088 = snd_soc_codec_get_drvdata(codec); | ||
1519 | struct max98088_cdata *cdata; | ||
1520 | u8 reg1Cval = 0; | ||
1521 | |||
1522 | cdata = &max98088->dai[1]; | ||
1523 | |||
1524 | if (fmt != cdata->fmt) { | ||
1525 | cdata->fmt = fmt; | ||
1526 | |||
1527 | switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { | ||
1528 | case SND_SOC_DAIFMT_CBS_CFS: | ||
1529 | /* Slave mode PLL */ | ||
1530 | snd_soc_write(codec, M98088_REG_1A_DAI2_CLKCFG_HI, | ||
1531 | 0x80); | ||
1532 | snd_soc_write(codec, M98088_REG_1B_DAI2_CLKCFG_LO, | ||
1533 | 0x00); | ||
1534 | break; | ||
1535 | case SND_SOC_DAIFMT_CBM_CFM: | ||
1536 | /* Set to master mode */ | ||
1537 | reg1Cval |= M98088_DAI_MAS; | ||
1538 | break; | ||
1539 | case SND_SOC_DAIFMT_CBS_CFM: | ||
1540 | case SND_SOC_DAIFMT_CBM_CFS: | ||
1541 | default: | ||
1542 | dev_err(codec->dev, "Clock mode unsupported"); | ||
1543 | return -EINVAL; | ||
1544 | } | ||
1545 | |||
1546 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { | ||
1547 | case SND_SOC_DAIFMT_I2S: | ||
1548 | reg1Cval |= M98088_DAI_DLY; | ||
1549 | break; | ||
1550 | case SND_SOC_DAIFMT_LEFT_J: | ||
1551 | break; | ||
1552 | default: | ||
1553 | return -EINVAL; | ||
1554 | } | ||
1555 | |||
1556 | switch (fmt & SND_SOC_DAIFMT_INV_MASK) { | ||
1557 | case SND_SOC_DAIFMT_NB_NF: | ||
1558 | break; | ||
1559 | case SND_SOC_DAIFMT_NB_IF: | ||
1560 | reg1Cval |= M98088_DAI_WCI; | ||
1561 | break; | ||
1562 | case SND_SOC_DAIFMT_IB_NF: | ||
1563 | reg1Cval |= M98088_DAI_BCI; | ||
1564 | break; | ||
1565 | case SND_SOC_DAIFMT_IB_IF: | ||
1566 | reg1Cval |= M98088_DAI_BCI|M98088_DAI_WCI; | ||
1567 | break; | ||
1568 | default: | ||
1569 | return -EINVAL; | ||
1570 | } | ||
1571 | |||
1572 | snd_soc_update_bits(codec, M98088_REG_1C_DAI2_FORMAT, | ||
1573 | M98088_DAI_MAS | M98088_DAI_DLY | M98088_DAI_BCI | | ||
1574 | M98088_DAI_WCI, reg1Cval); | ||
1575 | |||
1576 | snd_soc_write(codec, M98088_REG_1D_DAI2_CLOCK, | ||
1577 | M98088_DAI_BSEL64); | ||
1578 | } | ||
1579 | |||
1580 | return 0; | ||
1581 | } | ||
1582 | |||
1583 | static void max98088_sync_cache(struct snd_soc_codec *codec) | ||
1584 | { | ||
1585 | struct max98088_priv *max98088 = snd_soc_codec_get_drvdata(codec); | ||
1586 | int i; | ||
1587 | |||
1588 | if (!codec->cache_sync) | ||
1589 | return; | ||
1590 | |||
1591 | codec->cache_only = 0; | ||
1592 | |||
1593 | /* write back cached values if they're writeable and | ||
1594 | * different from the hardware default. | ||
1595 | */ | ||
1596 | for (i = 1; i < ARRAY_SIZE(max98088->reg_cache); i++) { | ||
1597 | if (!max98088_access[i].writable) | ||
1598 | continue; | ||
1599 | |||
1600 | if (max98088->reg_cache[i] == max98088_reg[i]) | ||
1601 | continue; | ||
1602 | |||
1603 | snd_soc_write(codec, i, max98088->reg_cache[i]); | ||
1604 | } | ||
1605 | |||
1606 | codec->cache_sync = 0; | ||
1607 | } | ||
1608 | |||
1609 | static int max98088_set_bias_level(struct snd_soc_codec *codec, | ||
1610 | enum snd_soc_bias_level level) | ||
1611 | { | ||
1612 | switch (level) { | ||
1613 | case SND_SOC_BIAS_ON: | ||
1614 | break; | ||
1615 | |||
1616 | case SND_SOC_BIAS_PREPARE: | ||
1617 | break; | ||
1618 | |||
1619 | case SND_SOC_BIAS_STANDBY: | ||
1620 | if (codec->bias_level == SND_SOC_BIAS_OFF) | ||
1621 | max98088_sync_cache(codec); | ||
1622 | |||
1623 | snd_soc_update_bits(codec, M98088_REG_4C_PWR_EN_IN, | ||
1624 | M98088_MBEN, M98088_MBEN); | ||
1625 | break; | ||
1626 | |||
1627 | case SND_SOC_BIAS_OFF: | ||
1628 | snd_soc_update_bits(codec, M98088_REG_4C_PWR_EN_IN, | ||
1629 | M98088_MBEN, 0); | ||
1630 | codec->cache_sync = 1; | ||
1631 | break; | ||
1632 | } | ||
1633 | codec->bias_level = level; | ||
1634 | return 0; | ||
1635 | } | ||
1636 | |||
1637 | #define MAX98088_RATES SNDRV_PCM_RATE_8000_96000 | ||
1638 | #define MAX98088_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE) | ||
1639 | |||
1640 | static struct snd_soc_dai_ops max98088_dai1_ops = { | ||
1641 | .set_sysclk = max98088_dai_set_sysclk, | ||
1642 | .set_fmt = max98088_dai1_set_fmt, | ||
1643 | .hw_params = max98088_dai1_hw_params, | ||
1644 | }; | ||
1645 | |||
1646 | static struct snd_soc_dai_ops max98088_dai2_ops = { | ||
1647 | .set_sysclk = max98088_dai_set_sysclk, | ||
1648 | .set_fmt = max98088_dai2_set_fmt, | ||
1649 | .hw_params = max98088_dai2_hw_params, | ||
1650 | }; | ||
1651 | |||
1652 | static struct snd_soc_dai_driver max98088_dai[] = { | ||
1653 | { | ||
1654 | .name = "HiFi", | ||
1655 | .playback = { | ||
1656 | .stream_name = "HiFi Playback", | ||
1657 | .channels_min = 1, | ||
1658 | .channels_max = 2, | ||
1659 | .rates = MAX98088_RATES, | ||
1660 | .formats = MAX98088_FORMATS, | ||
1661 | }, | ||
1662 | .capture = { | ||
1663 | .stream_name = "HiFi Capture", | ||
1664 | .channels_min = 1, | ||
1665 | .channels_max = 2, | ||
1666 | .rates = MAX98088_RATES, | ||
1667 | .formats = MAX98088_FORMATS, | ||
1668 | }, | ||
1669 | .ops = &max98088_dai1_ops, | ||
1670 | }, | ||
1671 | { | ||
1672 | .name = "Aux", | ||
1673 | .playback = { | ||
1674 | .stream_name = "Aux Playback", | ||
1675 | .channels_min = 1, | ||
1676 | .channels_max = 2, | ||
1677 | .rates = MAX98088_RATES, | ||
1678 | .formats = MAX98088_FORMATS, | ||
1679 | }, | ||
1680 | .ops = &max98088_dai2_ops, | ||
1681 | } | ||
1682 | }; | ||
1683 | |||
1684 | static int max98088_get_channel(const char *name) | ||
1685 | { | ||
1686 | if (strcmp(name, "EQ1 Mode") == 0) | ||
1687 | return 0; | ||
1688 | if (strcmp(name, "EQ2 Mode") == 0) | ||
1689 | return 1; | ||
1690 | return -EINVAL; | ||
1691 | } | ||
1692 | |||
1693 | static void max98088_setup_eq1(struct snd_soc_codec *codec) | ||
1694 | { | ||
1695 | struct max98088_priv *max98088 = snd_soc_codec_get_drvdata(codec); | ||
1696 | struct max98088_pdata *pdata = max98088->pdata; | ||
1697 | struct max98088_eq_cfg *coef_set; | ||
1698 | int best, best_val, save, i, sel, fs; | ||
1699 | struct max98088_cdata *cdata; | ||
1700 | |||
1701 | cdata = &max98088->dai[0]; | ||
1702 | |||
1703 | if (!pdata || !max98088->eq_textcnt) | ||
1704 | return; | ||
1705 | |||
1706 | /* Find the selected configuration with nearest sample rate */ | ||
1707 | fs = cdata->rate; | ||
1708 | sel = cdata->eq_sel; | ||
1709 | |||
1710 | best = 0; | ||
1711 | best_val = INT_MAX; | ||
1712 | for (i = 0; i < pdata->eq_cfgcnt; i++) { | ||
1713 | if (strcmp(pdata->eq_cfg[i].name, max98088->eq_texts[sel]) == 0 && | ||
1714 | abs(pdata->eq_cfg[i].rate - fs) < best_val) { | ||
1715 | best = i; | ||
1716 | best_val = abs(pdata->eq_cfg[i].rate - fs); | ||
1717 | } | ||
1718 | } | ||
1719 | |||
1720 | dev_dbg(codec->dev, "Selected %s/%dHz for %dHz sample rate\n", | ||
1721 | pdata->eq_cfg[best].name, | ||
1722 | pdata->eq_cfg[best].rate, fs); | ||
1723 | |||
1724 | /* Disable EQ while configuring, and save current on/off state */ | ||
1725 | save = snd_soc_read(codec, M98088_REG_49_CFG_LEVEL); | ||
1726 | snd_soc_update_bits(codec, M98088_REG_49_CFG_LEVEL, M98088_EQ1EN, 0); | ||
1727 | |||
1728 | coef_set = &pdata->eq_cfg[sel]; | ||
1729 | |||
1730 | m98088_eq_band(codec, 0, 0, coef_set->band1); | ||
1731 | m98088_eq_band(codec, 0, 1, coef_set->band2); | ||
1732 | m98088_eq_band(codec, 0, 2, coef_set->band3); | ||
1733 | m98088_eq_band(codec, 0, 3, coef_set->band4); | ||
1734 | m98088_eq_band(codec, 0, 4, coef_set->band5); | ||
1735 | |||
1736 | /* Restore the original on/off state */ | ||
1737 | snd_soc_update_bits(codec, M98088_REG_49_CFG_LEVEL, M98088_EQ1EN, save); | ||
1738 | } | ||
1739 | |||
1740 | static void max98088_setup_eq2(struct snd_soc_codec *codec) | ||
1741 | { | ||
1742 | struct max98088_priv *max98088 = snd_soc_codec_get_drvdata(codec); | ||
1743 | struct max98088_pdata *pdata = max98088->pdata; | ||
1744 | struct max98088_eq_cfg *coef_set; | ||
1745 | int best, best_val, save, i, sel, fs; | ||
1746 | struct max98088_cdata *cdata; | ||
1747 | |||
1748 | cdata = &max98088->dai[1]; | ||
1749 | |||
1750 | if (!pdata || !max98088->eq_textcnt) | ||
1751 | return; | ||
1752 | |||
1753 | /* Find the selected configuration with nearest sample rate */ | ||
1754 | fs = cdata->rate; | ||
1755 | |||
1756 | sel = cdata->eq_sel; | ||
1757 | best = 0; | ||
1758 | best_val = INT_MAX; | ||
1759 | for (i = 0; i < pdata->eq_cfgcnt; i++) { | ||
1760 | if (strcmp(pdata->eq_cfg[i].name, max98088->eq_texts[sel]) == 0 && | ||
1761 | abs(pdata->eq_cfg[i].rate - fs) < best_val) { | ||
1762 | best = i; | ||
1763 | best_val = abs(pdata->eq_cfg[i].rate - fs); | ||
1764 | } | ||
1765 | } | ||
1766 | |||
1767 | dev_dbg(codec->dev, "Selected %s/%dHz for %dHz sample rate\n", | ||
1768 | pdata->eq_cfg[best].name, | ||
1769 | pdata->eq_cfg[best].rate, fs); | ||
1770 | |||
1771 | /* Disable EQ while configuring, and save current on/off state */ | ||
1772 | save = snd_soc_read(codec, M98088_REG_49_CFG_LEVEL); | ||
1773 | snd_soc_update_bits(codec, M98088_REG_49_CFG_LEVEL, M98088_EQ2EN, 0); | ||
1774 | |||
1775 | coef_set = &pdata->eq_cfg[sel]; | ||
1776 | |||
1777 | m98088_eq_band(codec, 1, 0, coef_set->band1); | ||
1778 | m98088_eq_band(codec, 1, 1, coef_set->band2); | ||
1779 | m98088_eq_band(codec, 1, 2, coef_set->band3); | ||
1780 | m98088_eq_band(codec, 1, 3, coef_set->band4); | ||
1781 | m98088_eq_band(codec, 1, 4, coef_set->band5); | ||
1782 | |||
1783 | /* Restore the original on/off state */ | ||
1784 | snd_soc_update_bits(codec, M98088_REG_49_CFG_LEVEL, M98088_EQ2EN, | ||
1785 | save); | ||
1786 | } | ||
1787 | |||
1788 | static int max98088_put_eq_enum(struct snd_kcontrol *kcontrol, | ||
1789 | struct snd_ctl_elem_value *ucontrol) | ||
1790 | { | ||
1791 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | ||
1792 | struct max98088_priv *max98088 = snd_soc_codec_get_drvdata(codec); | ||
1793 | struct max98088_pdata *pdata = max98088->pdata; | ||
1794 | int channel = max98088_get_channel(kcontrol->id.name); | ||
1795 | struct max98088_cdata *cdata; | ||
1796 | int sel = ucontrol->value.integer.value[0]; | ||
1797 | |||
1798 | cdata = &max98088->dai[channel]; | ||
1799 | |||
1800 | if (sel >= pdata->eq_cfgcnt) | ||
1801 | return -EINVAL; | ||
1802 | |||
1803 | cdata->eq_sel = sel; | ||
1804 | |||
1805 | switch (channel) { | ||
1806 | case 0: | ||
1807 | max98088_setup_eq1(codec); | ||
1808 | break; | ||
1809 | case 1: | ||
1810 | max98088_setup_eq2(codec); | ||
1811 | break; | ||
1812 | } | ||
1813 | |||
1814 | return 0; | ||
1815 | } | ||
1816 | |||
1817 | static int max98088_get_eq_enum(struct snd_kcontrol *kcontrol, | ||
1818 | struct snd_ctl_elem_value *ucontrol) | ||
1819 | { | ||
1820 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | ||
1821 | struct max98088_priv *max98088 = snd_soc_codec_get_drvdata(codec); | ||
1822 | int channel = max98088_get_channel(kcontrol->id.name); | ||
1823 | struct max98088_cdata *cdata; | ||
1824 | |||
1825 | cdata = &max98088->dai[channel]; | ||
1826 | ucontrol->value.enumerated.item[0] = cdata->eq_sel; | ||
1827 | return 0; | ||
1828 | } | ||
1829 | |||
1830 | static void max98088_handle_eq_pdata(struct snd_soc_codec *codec) | ||
1831 | { | ||
1832 | struct max98088_priv *max98088 = snd_soc_codec_get_drvdata(codec); | ||
1833 | struct max98088_pdata *pdata = max98088->pdata; | ||
1834 | struct max98088_eq_cfg *cfg; | ||
1835 | unsigned int cfgcnt; | ||
1836 | int i, j; | ||
1837 | const char **t; | ||
1838 | int ret; | ||
1839 | |||
1840 | struct snd_kcontrol_new controls[] = { | ||
1841 | SOC_ENUM_EXT("EQ1 Mode", | ||
1842 | max98088->eq_enum, | ||
1843 | max98088_get_eq_enum, | ||
1844 | max98088_put_eq_enum), | ||
1845 | SOC_ENUM_EXT("EQ2 Mode", | ||
1846 | max98088->eq_enum, | ||
1847 | max98088_get_eq_enum, | ||
1848 | max98088_put_eq_enum), | ||
1849 | }; | ||
1850 | |||
1851 | cfg = pdata->eq_cfg; | ||
1852 | cfgcnt = pdata->eq_cfgcnt; | ||
1853 | |||
1854 | /* Setup an array of texts for the equalizer enum. | ||
1855 | * This is based on Mark Brown's equalizer driver code. | ||
1856 | */ | ||
1857 | max98088->eq_textcnt = 0; | ||
1858 | max98088->eq_texts = NULL; | ||
1859 | for (i = 0; i < cfgcnt; i++) { | ||
1860 | for (j = 0; j < max98088->eq_textcnt; j++) { | ||
1861 | if (strcmp(cfg[i].name, max98088->eq_texts[j]) == 0) | ||
1862 | break; | ||
1863 | } | ||
1864 | |||
1865 | if (j != max98088->eq_textcnt) | ||
1866 | continue; | ||
1867 | |||
1868 | /* Expand the array */ | ||
1869 | t = krealloc(max98088->eq_texts, | ||
1870 | sizeof(char *) * (max98088->eq_textcnt + 1), | ||
1871 | GFP_KERNEL); | ||
1872 | if (t == NULL) | ||
1873 | continue; | ||
1874 | |||
1875 | /* Store the new entry */ | ||
1876 | t[max98088->eq_textcnt] = cfg[i].name; | ||
1877 | max98088->eq_textcnt++; | ||
1878 | max98088->eq_texts = t; | ||
1879 | } | ||
1880 | |||
1881 | /* Now point the soc_enum to .texts array items */ | ||
1882 | max98088->eq_enum.texts = max98088->eq_texts; | ||
1883 | max98088->eq_enum.max = max98088->eq_textcnt; | ||
1884 | |||
1885 | ret = snd_soc_add_controls(codec, controls, ARRAY_SIZE(controls)); | ||
1886 | if (ret != 0) | ||
1887 | dev_err(codec->dev, "Failed to add EQ control: %d\n", ret); | ||
1888 | } | ||
1889 | |||
1890 | static void max98088_handle_pdata(struct snd_soc_codec *codec) | ||
1891 | { | ||
1892 | struct max98088_priv *max98088 = snd_soc_codec_get_drvdata(codec); | ||
1893 | struct max98088_pdata *pdata = max98088->pdata; | ||
1894 | u8 regval = 0; | ||
1895 | |||
1896 | if (!pdata) { | ||
1897 | dev_dbg(codec->dev, "No platform data\n"); | ||
1898 | return; | ||
1899 | } | ||
1900 | |||
1901 | /* Configure mic for analog/digital mic mode */ | ||
1902 | if (pdata->digmic_left_mode) | ||
1903 | regval |= M98088_DIGMIC_L; | ||
1904 | |||
1905 | if (pdata->digmic_right_mode) | ||
1906 | regval |= M98088_DIGMIC_R; | ||
1907 | |||
1908 | max98088->digmic = (regval ? 1 : 0); | ||
1909 | |||
1910 | snd_soc_write(codec, M98088_REG_48_CFG_MIC, regval); | ||
1911 | |||
1912 | /* Configure receiver output */ | ||
1913 | regval = ((pdata->receiver_mode) ? M98088_REC_LINEMODE : 0); | ||
1914 | snd_soc_update_bits(codec, M98088_REG_2A_MIC_REC_CNTL, | ||
1915 | M98088_REC_LINEMODE_MASK, regval); | ||
1916 | |||
1917 | /* Configure equalizers */ | ||
1918 | if (pdata->eq_cfgcnt) | ||
1919 | max98088_handle_eq_pdata(codec); | ||
1920 | } | ||
1921 | |||
1922 | #ifdef CONFIG_PM | ||
1923 | static int max98088_suspend(struct snd_soc_codec *codec, pm_message_t state) | ||
1924 | { | ||
1925 | max98088_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
1926 | |||
1927 | return 0; | ||
1928 | } | ||
1929 | |||
1930 | static int max98088_resume(struct snd_soc_codec *codec) | ||
1931 | { | ||
1932 | max98088_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
1933 | |||
1934 | return 0; | ||
1935 | } | ||
1936 | #else | ||
1937 | #define max98088_suspend NULL | ||
1938 | #define max98088_resume NULL | ||
1939 | #endif | ||
1940 | |||
1941 | static int max98088_probe(struct snd_soc_codec *codec) | ||
1942 | { | ||
1943 | struct max98088_priv *max98088 = snd_soc_codec_get_drvdata(codec); | ||
1944 | struct max98088_cdata *cdata; | ||
1945 | int ret = 0; | ||
1946 | |||
1947 | codec->cache_sync = 1; | ||
1948 | memcpy(codec->reg_cache, max98088_reg, sizeof(max98088_reg)); | ||
1949 | |||
1950 | ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_I2C); | ||
1951 | if (ret != 0) { | ||
1952 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); | ||
1953 | return ret; | ||
1954 | } | ||
1955 | |||
1956 | /* initalize private data */ | ||
1957 | |||
1958 | max98088->sysclk = (unsigned)-1; | ||
1959 | max98088->eq_textcnt = 0; | ||
1960 | |||
1961 | cdata = &max98088->dai[0]; | ||
1962 | cdata->rate = (unsigned)-1; | ||
1963 | cdata->fmt = (unsigned)-1; | ||
1964 | cdata->eq_sel = 0; | ||
1965 | |||
1966 | cdata = &max98088->dai[1]; | ||
1967 | cdata->rate = (unsigned)-1; | ||
1968 | cdata->fmt = (unsigned)-1; | ||
1969 | cdata->eq_sel = 0; | ||
1970 | |||
1971 | max98088->ina_state = 0; | ||
1972 | max98088->inb_state = 0; | ||
1973 | max98088->ex_mode = 0; | ||
1974 | max98088->digmic = 0; | ||
1975 | max98088->mic1pre = 0; | ||
1976 | max98088->mic2pre = 0; | ||
1977 | |||
1978 | ret = snd_soc_read(codec, M98088_REG_FF_REV_ID); | ||
1979 | if (ret < 0) { | ||
1980 | dev_err(codec->dev, "Failed to read device revision: %d\n", | ||
1981 | ret); | ||
1982 | goto err_access; | ||
1983 | } | ||
1984 | dev_info(codec->dev, "revision %c\n", ret + 'A'); | ||
1985 | |||
1986 | snd_soc_write(codec, M98088_REG_51_PWR_SYS, M98088_PWRSV); | ||
1987 | |||
1988 | /* initialize registers cache to hardware default */ | ||
1989 | max98088_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
1990 | |||
1991 | snd_soc_write(codec, M98088_REG_0F_IRQ_ENABLE, 0x00); | ||
1992 | |||
1993 | snd_soc_write(codec, M98088_REG_22_MIX_DAC, | ||
1994 | M98088_DAI1L_TO_DACL|M98088_DAI2L_TO_DACL| | ||
1995 | M98088_DAI1R_TO_DACR|M98088_DAI2R_TO_DACR); | ||
1996 | |||
1997 | snd_soc_write(codec, M98088_REG_4E_BIAS_CNTL, 0xF0); | ||
1998 | snd_soc_write(codec, M98088_REG_50_DAC_BIAS2, 0x0F); | ||
1999 | |||
2000 | snd_soc_write(codec, M98088_REG_16_DAI1_IOCFG, | ||
2001 | M98088_S1NORMAL|M98088_SDATA); | ||
2002 | |||
2003 | snd_soc_write(codec, M98088_REG_1E_DAI2_IOCFG, | ||
2004 | M98088_S2NORMAL|M98088_SDATA); | ||
2005 | |||
2006 | max98088_handle_pdata(codec); | ||
2007 | |||
2008 | max98088_add_widgets(codec); | ||
2009 | |||
2010 | err_access: | ||
2011 | return ret; | ||
2012 | } | ||
2013 | |||
2014 | static int max98088_remove(struct snd_soc_codec *codec) | ||
2015 | { | ||
2016 | max98088_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
2017 | |||
2018 | return 0; | ||
2019 | } | ||
2020 | |||
2021 | static struct snd_soc_codec_driver soc_codec_dev_max98088 = { | ||
2022 | .probe = max98088_probe, | ||
2023 | .remove = max98088_remove, | ||
2024 | .suspend = max98088_suspend, | ||
2025 | .resume = max98088_resume, | ||
2026 | .set_bias_level = max98088_set_bias_level, | ||
2027 | .reg_cache_size = ARRAY_SIZE(max98088_reg), | ||
2028 | .reg_word_size = sizeof(u8), | ||
2029 | .reg_cache_default = max98088_reg, | ||
2030 | .volatile_register = max98088_volatile_register, | ||
2031 | }; | ||
2032 | |||
2033 | static int max98088_i2c_probe(struct i2c_client *i2c, | ||
2034 | const struct i2c_device_id *id) | ||
2035 | { | ||
2036 | struct max98088_priv *max98088; | ||
2037 | int ret; | ||
2038 | |||
2039 | max98088 = kzalloc(sizeof(struct max98088_priv), GFP_KERNEL); | ||
2040 | if (max98088 == NULL) | ||
2041 | return -ENOMEM; | ||
2042 | |||
2043 | i2c_set_clientdata(i2c, max98088); | ||
2044 | max98088->control_data = i2c; | ||
2045 | max98088->pdata = i2c->dev.platform_data; | ||
2046 | |||
2047 | ret = snd_soc_register_codec(&i2c->dev, | ||
2048 | &soc_codec_dev_max98088, &max98088_dai[0], 2); | ||
2049 | if (ret < 0) | ||
2050 | kfree(max98088); | ||
2051 | return ret; | ||
2052 | } | ||
2053 | |||
2054 | static int max98088_i2c_remove(struct i2c_client *client) | ||
2055 | { | ||
2056 | snd_soc_unregister_codec(&client->dev); | ||
2057 | kfree(i2c_get_clientdata(client)); | ||
2058 | return 0; | ||
2059 | } | ||
2060 | |||
2061 | static const struct i2c_device_id max98088_i2c_id[] = { | ||
2062 | { "max98088", 0 }, | ||
2063 | { } | ||
2064 | }; | ||
2065 | MODULE_DEVICE_TABLE(i2c, max98088_i2c_id); | ||
2066 | |||
2067 | static struct i2c_driver max98088_i2c_driver = { | ||
2068 | .driver = { | ||
2069 | .name = "max98088", | ||
2070 | .owner = THIS_MODULE, | ||
2071 | }, | ||
2072 | .probe = max98088_i2c_probe, | ||
2073 | .remove = __devexit_p(max98088_i2c_remove), | ||
2074 | .id_table = max98088_i2c_id, | ||
2075 | }; | ||
2076 | |||
2077 | static int __init max98088_init(void) | ||
2078 | { | ||
2079 | int ret; | ||
2080 | |||
2081 | ret = i2c_add_driver(&max98088_i2c_driver); | ||
2082 | if (ret) | ||
2083 | pr_err("Failed to register max98088 I2C driver: %d\n", ret); | ||
2084 | |||
2085 | return ret; | ||
2086 | } | ||
2087 | module_init(max98088_init); | ||
2088 | |||
2089 | static void __exit max98088_exit(void) | ||
2090 | { | ||
2091 | i2c_del_driver(&max98088_i2c_driver); | ||
2092 | } | ||
2093 | module_exit(max98088_exit); | ||
2094 | |||
2095 | MODULE_DESCRIPTION("ALSA SoC MAX98088 driver"); | ||
2096 | MODULE_AUTHOR("Peter Hsiang, Jesse Marroquin"); | ||
2097 | MODULE_LICENSE("GPL"); | ||