1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* |
3 | * ADAU1977/ADAU1978/ADAU1979 driver |
4 | * |
5 | * Copyright 2014 Analog Devices Inc. |
6 | * Author: Lars-Peter Clausen <lars@metafoo.de> |
7 | */ |
8 | |
9 | #include <linux/delay.h> |
10 | #include <linux/device.h> |
11 | #include <linux/gpio/consumer.h> |
12 | #include <linux/i2c.h> |
13 | #include <linux/init.h> |
14 | #include <linux/module.h> |
15 | #include <linux/regmap.h> |
16 | #include <linux/regulator/consumer.h> |
17 | #include <linux/slab.h> |
18 | |
19 | #include <sound/core.h> |
20 | #include <sound/initval.h> |
21 | #include <sound/pcm.h> |
22 | #include <sound/pcm_params.h> |
23 | #include <sound/soc.h> |
24 | #include <sound/tlv.h> |
25 | |
26 | #include <dt-bindings/sound/adi,adau1977.h> |
27 | |
28 | #include "adau1977.h" |
29 | |
30 | #define ADAU1977_REG_POWER 0x00 |
31 | #define ADAU1977_REG_PLL 0x01 |
32 | #define ADAU1977_REG_BOOST 0x02 |
33 | #define ADAU1977_REG_MICBIAS 0x03 |
34 | #define ADAU1977_REG_BLOCK_POWER_SAI 0x04 |
35 | #define ADAU1977_REG_SAI_CTRL0 0x05 |
36 | #define ADAU1977_REG_SAI_CTRL1 0x06 |
37 | #define ADAU1977_REG_CMAP12 0x07 |
38 | #define ADAU1977_REG_CMAP34 0x08 |
39 | #define ADAU1977_REG_SAI_OVERTEMP 0x09 |
40 | #define ADAU1977_REG_POST_ADC_GAIN(x) (0x0a + (x)) |
41 | #define ADAU1977_REG_MISC_CONTROL 0x0e |
42 | #define ADAU1977_REG_DIAG_CONTROL 0x10 |
43 | #define ADAU1977_REG_STATUS(x) (0x11 + (x)) |
44 | #define ADAU1977_REG_DIAG_IRQ1 0x15 |
45 | #define ADAU1977_REG_DIAG_IRQ2 0x16 |
46 | #define ADAU1977_REG_ADJUST1 0x17 |
47 | #define ADAU1977_REG_ADJUST2 0x18 |
48 | #define ADAU1977_REG_ADC_CLIP 0x19 |
49 | #define ADAU1977_REG_DC_HPF_CAL 0x1a |
50 | |
51 | #define ADAU1977_POWER_RESET BIT(7) |
52 | #define ADAU1977_POWER_PWUP BIT(0) |
53 | |
54 | #define ADAU1977_PLL_CLK_S BIT(4) |
55 | #define ADAU1977_PLL_MCS_MASK 0x7 |
56 | |
57 | #define ADAU1977_MICBIAS_MB_VOLTS_MASK 0xf0 |
58 | #define ADAU1977_MICBIAS_MB_VOLTS_OFFSET 4 |
59 | |
60 | #define ADAU1977_BLOCK_POWER_SAI_LR_POL BIT(7) |
61 | #define ADAU1977_BLOCK_POWER_SAI_BCLK_EDGE BIT(6) |
62 | #define ADAU1977_BLOCK_POWER_SAI_LDO_EN BIT(5) |
63 | |
64 | #define ADAU1977_SAI_CTRL0_FMT_MASK (0x3 << 6) |
65 | #define ADAU1977_SAI_CTRL0_FMT_I2S (0x0 << 6) |
66 | #define ADAU1977_SAI_CTRL0_FMT_LJ (0x1 << 6) |
67 | #define ADAU1977_SAI_CTRL0_FMT_RJ_24BIT (0x2 << 6) |
68 | #define ADAU1977_SAI_CTRL0_FMT_RJ_16BIT (0x3 << 6) |
69 | |
70 | #define ADAU1977_SAI_CTRL0_SAI_MASK (0x7 << 3) |
71 | #define ADAU1977_SAI_CTRL0_SAI_I2S (0x0 << 3) |
72 | #define ADAU1977_SAI_CTRL0_SAI_TDM_2 (0x1 << 3) |
73 | #define ADAU1977_SAI_CTRL0_SAI_TDM_4 (0x2 << 3) |
74 | #define ADAU1977_SAI_CTRL0_SAI_TDM_8 (0x3 << 3) |
75 | #define ADAU1977_SAI_CTRL0_SAI_TDM_16 (0x4 << 3) |
76 | |
77 | #define ADAU1977_SAI_CTRL0_FS_MASK (0x7) |
78 | #define ADAU1977_SAI_CTRL0_FS_8000_12000 (0x0) |
79 | #define ADAU1977_SAI_CTRL0_FS_16000_24000 (0x1) |
80 | #define ADAU1977_SAI_CTRL0_FS_32000_48000 (0x2) |
81 | #define ADAU1977_SAI_CTRL0_FS_64000_96000 (0x3) |
82 | #define ADAU1977_SAI_CTRL0_FS_128000_192000 (0x4) |
83 | |
84 | #define ADAU1977_SAI_CTRL1_SLOT_WIDTH_MASK (0x3 << 5) |
85 | #define ADAU1977_SAI_CTRL1_SLOT_WIDTH_32 (0x0 << 5) |
86 | #define ADAU1977_SAI_CTRL1_SLOT_WIDTH_24 (0x1 << 5) |
87 | #define ADAU1977_SAI_CTRL1_SLOT_WIDTH_16 (0x2 << 5) |
88 | #define ADAU1977_SAI_CTRL1_DATA_WIDTH_MASK (0x1 << 4) |
89 | #define ADAU1977_SAI_CTRL1_DATA_WIDTH_16BIT (0x1 << 4) |
90 | #define ADAU1977_SAI_CTRL1_DATA_WIDTH_24BIT (0x0 << 4) |
91 | #define ADAU1977_SAI_CTRL1_LRCLK_PULSE BIT(3) |
92 | #define ADAU1977_SAI_CTRL1_MSB BIT(2) |
93 | #define ADAU1977_SAI_CTRL1_BCLKRATE_16 (0x1 << 1) |
94 | #define ADAU1977_SAI_CTRL1_BCLKRATE_32 (0x0 << 1) |
95 | #define ADAU1977_SAI_CTRL1_BCLKRATE_MASK (0x1 << 1) |
96 | #define ADAU1977_SAI_CTRL1_MASTER BIT(0) |
97 | |
98 | #define ADAU1977_SAI_OVERTEMP_DRV_C(x) BIT(4 + (x)) |
99 | #define ADAU1977_SAI_OVERTEMP_DRV_HIZ BIT(3) |
100 | |
101 | #define ADAU1977_MISC_CONTROL_SUM_MODE_MASK (0x3 << 6) |
102 | #define ADAU1977_MISC_CONTROL_SUM_MODE_1CH (0x2 << 6) |
103 | #define ADAU1977_MISC_CONTROL_SUM_MODE_2CH (0x1 << 6) |
104 | #define ADAU1977_MISC_CONTROL_SUM_MODE_4CH (0x0 << 6) |
105 | #define ADAU1977_MISC_CONTROL_MMUTE BIT(4) |
106 | #define ADAU1977_MISC_CONTROL_DC_CAL BIT(0) |
107 | |
108 | #define ADAU1977_CHAN_MAP_SECOND_SLOT_OFFSET 4 |
109 | #define ADAU1977_CHAN_MAP_FIRST_SLOT_OFFSET 0 |
110 | |
111 | struct adau1977 { |
112 | struct regmap *regmap; |
113 | bool right_j; |
114 | unsigned int sysclk; |
115 | enum adau1977_sysclk_src sysclk_src; |
116 | struct gpio_desc *reset_gpio; |
117 | enum adau1977_type type; |
118 | |
119 | struct regulator *avdd_reg; |
120 | struct regulator *dvdd_reg; |
121 | |
122 | struct snd_pcm_hw_constraint_list constraints; |
123 | |
124 | struct device *dev; |
125 | void (*switch_mode)(struct device *dev); |
126 | |
127 | unsigned int max_clock_provider_fs; |
128 | unsigned int slot_width; |
129 | bool enabled; |
130 | bool clock_provider; |
131 | }; |
132 | |
133 | static const struct reg_default adau1977_reg_defaults[] = { |
134 | { 0x00, 0x00 }, |
135 | { 0x01, 0x41 }, |
136 | { 0x02, 0x4a }, |
137 | { 0x03, 0x7d }, |
138 | { 0x04, 0x3d }, |
139 | { 0x05, 0x02 }, |
140 | { 0x06, 0x00 }, |
141 | { 0x07, 0x10 }, |
142 | { 0x08, 0x32 }, |
143 | { 0x09, 0xf0 }, |
144 | { 0x0a, 0xa0 }, |
145 | { 0x0b, 0xa0 }, |
146 | { 0x0c, 0xa0 }, |
147 | { 0x0d, 0xa0 }, |
148 | { 0x0e, 0x02 }, |
149 | { 0x10, 0x0f }, |
150 | { 0x15, 0x20 }, |
151 | { 0x16, 0x00 }, |
152 | { 0x17, 0x00 }, |
153 | { 0x18, 0x00 }, |
154 | { 0x1a, 0x00 }, |
155 | }; |
156 | |
157 | static const DECLARE_TLV_DB_MINMAX_MUTE(adau1977_adc_gain, -3562, 6000); |
158 | |
159 | static const struct snd_soc_dapm_widget adau1977_micbias_dapm_widgets[] = { |
160 | SND_SOC_DAPM_SUPPLY("MICBIAS" , ADAU1977_REG_MICBIAS, |
161 | 3, 0, NULL, 0) |
162 | }; |
163 | |
164 | static const struct snd_soc_dapm_widget adau1977_dapm_widgets[] = { |
165 | SND_SOC_DAPM_SUPPLY("Vref" , ADAU1977_REG_BLOCK_POWER_SAI, |
166 | 4, 0, NULL, 0), |
167 | |
168 | SND_SOC_DAPM_ADC("ADC1" , "Capture" , ADAU1977_REG_BLOCK_POWER_SAI, 0, 0), |
169 | SND_SOC_DAPM_ADC("ADC2" , "Capture" , ADAU1977_REG_BLOCK_POWER_SAI, 1, 0), |
170 | SND_SOC_DAPM_ADC("ADC3" , "Capture" , ADAU1977_REG_BLOCK_POWER_SAI, 2, 0), |
171 | SND_SOC_DAPM_ADC("ADC4" , "Capture" , ADAU1977_REG_BLOCK_POWER_SAI, 3, 0), |
172 | |
173 | SND_SOC_DAPM_INPUT("AIN1" ), |
174 | SND_SOC_DAPM_INPUT("AIN2" ), |
175 | SND_SOC_DAPM_INPUT("AIN3" ), |
176 | SND_SOC_DAPM_INPUT("AIN4" ), |
177 | |
178 | SND_SOC_DAPM_OUTPUT("VREF" ), |
179 | }; |
180 | |
181 | static const struct snd_soc_dapm_route adau1977_dapm_routes[] = { |
182 | { "ADC1" , NULL, "AIN1" }, |
183 | { "ADC2" , NULL, "AIN2" }, |
184 | { "ADC3" , NULL, "AIN3" }, |
185 | { "ADC4" , NULL, "AIN4" }, |
186 | |
187 | { "ADC1" , NULL, "Vref" }, |
188 | { "ADC2" , NULL, "Vref" }, |
189 | { "ADC3" , NULL, "Vref" }, |
190 | { "ADC4" , NULL, "Vref" }, |
191 | |
192 | { "VREF" , NULL, "Vref" }, |
193 | }; |
194 | |
195 | #define ADAU1977_VOLUME(x) \ |
196 | SOC_SINGLE_TLV("ADC" #x " Capture Volume", \ |
197 | ADAU1977_REG_POST_ADC_GAIN((x) - 1), \ |
198 | 0, 255, 1, adau1977_adc_gain) |
199 | |
200 | #define ADAU1977_HPF_SWITCH(x) \ |
201 | SOC_SINGLE("ADC" #x " Highpass-Filter Capture Switch", \ |
202 | ADAU1977_REG_DC_HPF_CAL, (x) - 1, 1, 0) |
203 | |
204 | #define ADAU1977_DC_SUB_SWITCH(x) \ |
205 | SOC_SINGLE("ADC" #x " DC Subtraction Capture Switch", \ |
206 | ADAU1977_REG_DC_HPF_CAL, (x) + 3, 1, 0) |
207 | |
208 | static const struct snd_kcontrol_new adau1977_snd_controls[] = { |
209 | ADAU1977_VOLUME(1), |
210 | ADAU1977_VOLUME(2), |
211 | ADAU1977_VOLUME(3), |
212 | ADAU1977_VOLUME(4), |
213 | |
214 | ADAU1977_HPF_SWITCH(1), |
215 | ADAU1977_HPF_SWITCH(2), |
216 | ADAU1977_HPF_SWITCH(3), |
217 | ADAU1977_HPF_SWITCH(4), |
218 | |
219 | ADAU1977_DC_SUB_SWITCH(1), |
220 | ADAU1977_DC_SUB_SWITCH(2), |
221 | ADAU1977_DC_SUB_SWITCH(3), |
222 | ADAU1977_DC_SUB_SWITCH(4), |
223 | }; |
224 | |
225 | static int adau1977_reset(struct adau1977 *adau1977) |
226 | { |
227 | int ret; |
228 | |
229 | /* |
230 | * The reset bit is obviously volatile, but we need to be able to cache |
231 | * the other bits in the register, so we can't just mark the whole |
232 | * register as volatile. Since this is the only place where we'll ever |
233 | * touch the reset bit just bypass the cache for this operation. |
234 | */ |
235 | regcache_cache_bypass(map: adau1977->regmap, enable: true); |
236 | ret = regmap_write(map: adau1977->regmap, ADAU1977_REG_POWER, |
237 | ADAU1977_POWER_RESET); |
238 | regcache_cache_bypass(map: adau1977->regmap, enable: false); |
239 | |
240 | return ret; |
241 | } |
242 | |
243 | /* |
244 | * Returns the appropriate setting for ths FS field in the CTRL0 register |
245 | * depending on the rate. |
246 | */ |
247 | static int adau1977_lookup_fs(unsigned int rate) |
248 | { |
249 | if (rate >= 8000 && rate <= 12000) |
250 | return ADAU1977_SAI_CTRL0_FS_8000_12000; |
251 | else if (rate >= 16000 && rate <= 24000) |
252 | return ADAU1977_SAI_CTRL0_FS_16000_24000; |
253 | else if (rate >= 32000 && rate <= 48000) |
254 | return ADAU1977_SAI_CTRL0_FS_32000_48000; |
255 | else if (rate >= 64000 && rate <= 96000) |
256 | return ADAU1977_SAI_CTRL0_FS_64000_96000; |
257 | else if (rate >= 128000 && rate <= 192000) |
258 | return ADAU1977_SAI_CTRL0_FS_128000_192000; |
259 | else |
260 | return -EINVAL; |
261 | } |
262 | |
263 | static int adau1977_lookup_mcs(struct adau1977 *adau1977, unsigned int rate, |
264 | unsigned int fs) |
265 | { |
266 | unsigned int mcs; |
267 | |
268 | /* |
269 | * rate = sysclk / (512 * mcs_lut[mcs]) * 2**fs |
270 | * => mcs_lut[mcs] = sysclk / (512 * rate) * 2**fs |
271 | * => mcs_lut[mcs] = sysclk / ((512 / 2**fs) * rate) |
272 | */ |
273 | |
274 | rate *= 512 >> fs; |
275 | |
276 | if (adau1977->sysclk % rate != 0) |
277 | return -EINVAL; |
278 | |
279 | mcs = adau1977->sysclk / rate; |
280 | |
281 | /* The factors configured by MCS are 1, 2, 3, 4, 6 */ |
282 | if (mcs < 1 || mcs > 6 || mcs == 5) |
283 | return -EINVAL; |
284 | |
285 | mcs = mcs - 1; |
286 | if (mcs == 5) |
287 | mcs = 4; |
288 | |
289 | return mcs; |
290 | } |
291 | |
292 | static int adau1977_hw_params(struct snd_pcm_substream *substream, |
293 | struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) |
294 | { |
295 | struct snd_soc_component *component = dai->component; |
296 | struct adau1977 *adau1977 = snd_soc_component_get_drvdata(c: component); |
297 | unsigned int rate = params_rate(p: params); |
298 | unsigned int slot_width; |
299 | unsigned int ctrl0, ctrl0_mask; |
300 | unsigned int ctrl1; |
301 | int mcs, fs; |
302 | int ret; |
303 | |
304 | fs = adau1977_lookup_fs(rate); |
305 | if (fs < 0) |
306 | return fs; |
307 | |
308 | if (adau1977->sysclk_src == ADAU1977_SYSCLK_SRC_MCLK) { |
309 | mcs = adau1977_lookup_mcs(adau1977, rate, fs); |
310 | if (mcs < 0) |
311 | return mcs; |
312 | } else { |
313 | mcs = 0; |
314 | } |
315 | |
316 | ctrl0_mask = ADAU1977_SAI_CTRL0_FS_MASK; |
317 | ctrl0 = fs; |
318 | |
319 | if (adau1977->right_j) { |
320 | switch (params_width(p: params)) { |
321 | case 16: |
322 | ctrl0 |= ADAU1977_SAI_CTRL0_FMT_RJ_16BIT; |
323 | break; |
324 | case 24: |
325 | ctrl0 |= ADAU1977_SAI_CTRL0_FMT_RJ_24BIT; |
326 | break; |
327 | default: |
328 | return -EINVAL; |
329 | } |
330 | ctrl0_mask |= ADAU1977_SAI_CTRL0_FMT_MASK; |
331 | } |
332 | |
333 | if (adau1977->clock_provider) { |
334 | switch (params_width(p: params)) { |
335 | case 16: |
336 | ctrl1 = ADAU1977_SAI_CTRL1_DATA_WIDTH_16BIT; |
337 | slot_width = 16; |
338 | break; |
339 | case 24: |
340 | case 32: |
341 | ctrl1 = ADAU1977_SAI_CTRL1_DATA_WIDTH_24BIT; |
342 | slot_width = 32; |
343 | break; |
344 | default: |
345 | return -EINVAL; |
346 | } |
347 | |
348 | /* In TDM mode there is a fixed slot width */ |
349 | if (adau1977->slot_width) |
350 | slot_width = adau1977->slot_width; |
351 | |
352 | if (slot_width == 16) |
353 | ctrl1 |= ADAU1977_SAI_CTRL1_BCLKRATE_16; |
354 | else |
355 | ctrl1 |= ADAU1977_SAI_CTRL1_BCLKRATE_32; |
356 | |
357 | ret = regmap_update_bits(map: adau1977->regmap, |
358 | ADAU1977_REG_SAI_CTRL1, |
359 | ADAU1977_SAI_CTRL1_DATA_WIDTH_MASK | |
360 | ADAU1977_SAI_CTRL1_BCLKRATE_MASK, |
361 | val: ctrl1); |
362 | if (ret < 0) |
363 | return ret; |
364 | } |
365 | |
366 | ret = regmap_update_bits(map: adau1977->regmap, ADAU1977_REG_SAI_CTRL0, |
367 | mask: ctrl0_mask, val: ctrl0); |
368 | if (ret < 0) |
369 | return ret; |
370 | |
371 | return regmap_update_bits(map: adau1977->regmap, ADAU1977_REG_PLL, |
372 | ADAU1977_PLL_MCS_MASK, val: mcs); |
373 | } |
374 | |
375 | static int adau1977_power_disable(struct adau1977 *adau1977) |
376 | { |
377 | int ret = 0; |
378 | |
379 | if (!adau1977->enabled) |
380 | return 0; |
381 | |
382 | ret = regmap_update_bits(map: adau1977->regmap, ADAU1977_REG_POWER, |
383 | ADAU1977_POWER_PWUP, val: 0); |
384 | if (ret) |
385 | return ret; |
386 | |
387 | regcache_mark_dirty(map: adau1977->regmap); |
388 | |
389 | gpiod_set_value_cansleep(desc: adau1977->reset_gpio, value: 0); |
390 | |
391 | regcache_cache_only(map: adau1977->regmap, enable: true); |
392 | |
393 | regulator_disable(regulator: adau1977->avdd_reg); |
394 | if (adau1977->dvdd_reg) |
395 | regulator_disable(regulator: adau1977->dvdd_reg); |
396 | |
397 | adau1977->enabled = false; |
398 | |
399 | return 0; |
400 | } |
401 | |
402 | static int adau1977_power_enable(struct adau1977 *adau1977) |
403 | { |
404 | unsigned int val; |
405 | int ret = 0; |
406 | |
407 | if (adau1977->enabled) |
408 | return 0; |
409 | |
410 | ret = regulator_enable(regulator: adau1977->avdd_reg); |
411 | if (ret) |
412 | return ret; |
413 | |
414 | if (adau1977->dvdd_reg) { |
415 | ret = regulator_enable(regulator: adau1977->dvdd_reg); |
416 | if (ret) |
417 | goto err_disable_avdd; |
418 | } |
419 | |
420 | gpiod_set_value_cansleep(desc: adau1977->reset_gpio, value: 1); |
421 | |
422 | regcache_cache_only(map: adau1977->regmap, enable: false); |
423 | |
424 | if (adau1977->switch_mode) |
425 | adau1977->switch_mode(adau1977->dev); |
426 | |
427 | ret = adau1977_reset(adau1977); |
428 | if (ret) |
429 | goto err_disable_dvdd; |
430 | |
431 | ret = regmap_update_bits(map: adau1977->regmap, ADAU1977_REG_POWER, |
432 | ADAU1977_POWER_PWUP, ADAU1977_POWER_PWUP); |
433 | if (ret) |
434 | goto err_disable_dvdd; |
435 | |
436 | ret = regcache_sync(map: adau1977->regmap); |
437 | if (ret) |
438 | goto err_disable_dvdd; |
439 | |
440 | /* |
441 | * The PLL register is not affected by the software reset. It is |
442 | * possible that the value of the register was changed to the |
443 | * default value while we were in cache only mode. In this case |
444 | * regcache_sync will skip over it and we have to manually sync |
445 | * it. |
446 | */ |
447 | ret = regmap_read(map: adau1977->regmap, ADAU1977_REG_PLL, val: &val); |
448 | if (ret) |
449 | goto err_disable_dvdd; |
450 | |
451 | if (val == 0x41) { |
452 | regcache_cache_bypass(map: adau1977->regmap, enable: true); |
453 | ret = regmap_write(map: adau1977->regmap, ADAU1977_REG_PLL, |
454 | val: 0x41); |
455 | if (ret) |
456 | goto err_disable_dvdd; |
457 | regcache_cache_bypass(map: adau1977->regmap, enable: false); |
458 | } |
459 | |
460 | adau1977->enabled = true; |
461 | |
462 | return ret; |
463 | |
464 | err_disable_dvdd: |
465 | if (adau1977->dvdd_reg) |
466 | regulator_disable(regulator: adau1977->dvdd_reg); |
467 | err_disable_avdd: |
468 | regulator_disable(regulator: adau1977->avdd_reg); |
469 | return ret; |
470 | } |
471 | |
472 | static int adau1977_set_bias_level(struct snd_soc_component *component, |
473 | enum snd_soc_bias_level level) |
474 | { |
475 | struct adau1977 *adau1977 = snd_soc_component_get_drvdata(c: component); |
476 | int ret = 0; |
477 | |
478 | switch (level) { |
479 | case SND_SOC_BIAS_ON: |
480 | break; |
481 | case SND_SOC_BIAS_PREPARE: |
482 | break; |
483 | case SND_SOC_BIAS_STANDBY: |
484 | if (snd_soc_component_get_bias_level(component) == SND_SOC_BIAS_OFF) |
485 | ret = adau1977_power_enable(adau1977); |
486 | break; |
487 | case SND_SOC_BIAS_OFF: |
488 | ret = adau1977_power_disable(adau1977); |
489 | break; |
490 | } |
491 | |
492 | return ret; |
493 | } |
494 | |
495 | static int adau1977_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask, |
496 | unsigned int rx_mask, int slots, int width) |
497 | { |
498 | struct adau1977 *adau1977 = snd_soc_component_get_drvdata(c: dai->component); |
499 | unsigned int ctrl0, ctrl1, drv; |
500 | unsigned int slot[4]; |
501 | unsigned int i; |
502 | int ret; |
503 | |
504 | if (slots == 0) { |
505 | /* 0 = No fixed slot width */ |
506 | adau1977->slot_width = 0; |
507 | adau1977->max_clock_provider_fs = 192000; |
508 | return regmap_update_bits(map: adau1977->regmap, |
509 | ADAU1977_REG_SAI_CTRL0, ADAU1977_SAI_CTRL0_SAI_MASK, |
510 | ADAU1977_SAI_CTRL0_SAI_I2S); |
511 | } |
512 | |
513 | if (rx_mask == 0 || tx_mask != 0) |
514 | return -EINVAL; |
515 | |
516 | drv = 0; |
517 | for (i = 0; i < 4; i++) { |
518 | slot[i] = __ffs(rx_mask); |
519 | drv |= ADAU1977_SAI_OVERTEMP_DRV_C(i); |
520 | rx_mask &= ~(1 << slot[i]); |
521 | if (slot[i] >= slots) |
522 | return -EINVAL; |
523 | if (rx_mask == 0) |
524 | break; |
525 | } |
526 | |
527 | if (rx_mask != 0) |
528 | return -EINVAL; |
529 | |
530 | switch (width) { |
531 | case 16: |
532 | ctrl1 = ADAU1977_SAI_CTRL1_SLOT_WIDTH_16; |
533 | break; |
534 | case 24: |
535 | /* We can only generate 16 bit or 32 bit wide slots */ |
536 | if (adau1977->clock_provider) |
537 | return -EINVAL; |
538 | ctrl1 = ADAU1977_SAI_CTRL1_SLOT_WIDTH_24; |
539 | break; |
540 | case 32: |
541 | ctrl1 = ADAU1977_SAI_CTRL1_SLOT_WIDTH_32; |
542 | break; |
543 | default: |
544 | return -EINVAL; |
545 | } |
546 | |
547 | switch (slots) { |
548 | case 2: |
549 | ctrl0 = ADAU1977_SAI_CTRL0_SAI_TDM_2; |
550 | break; |
551 | case 4: |
552 | ctrl0 = ADAU1977_SAI_CTRL0_SAI_TDM_4; |
553 | break; |
554 | case 8: |
555 | ctrl0 = ADAU1977_SAI_CTRL0_SAI_TDM_8; |
556 | break; |
557 | case 16: |
558 | ctrl0 = ADAU1977_SAI_CTRL0_SAI_TDM_16; |
559 | break; |
560 | default: |
561 | return -EINVAL; |
562 | } |
563 | |
564 | ret = regmap_update_bits(map: adau1977->regmap, ADAU1977_REG_SAI_OVERTEMP, |
565 | ADAU1977_SAI_OVERTEMP_DRV_C(0) | |
566 | ADAU1977_SAI_OVERTEMP_DRV_C(1) | |
567 | ADAU1977_SAI_OVERTEMP_DRV_C(2) | |
568 | ADAU1977_SAI_OVERTEMP_DRV_C(3), val: drv); |
569 | if (ret) |
570 | return ret; |
571 | |
572 | ret = regmap_write(map: adau1977->regmap, ADAU1977_REG_CMAP12, |
573 | val: (slot[1] << ADAU1977_CHAN_MAP_SECOND_SLOT_OFFSET) | |
574 | (slot[0] << ADAU1977_CHAN_MAP_FIRST_SLOT_OFFSET)); |
575 | if (ret) |
576 | return ret; |
577 | |
578 | ret = regmap_write(map: adau1977->regmap, ADAU1977_REG_CMAP34, |
579 | val: (slot[3] << ADAU1977_CHAN_MAP_SECOND_SLOT_OFFSET) | |
580 | (slot[2] << ADAU1977_CHAN_MAP_FIRST_SLOT_OFFSET)); |
581 | if (ret) |
582 | return ret; |
583 | |
584 | ret = regmap_update_bits(map: adau1977->regmap, ADAU1977_REG_SAI_CTRL0, |
585 | ADAU1977_SAI_CTRL0_SAI_MASK, val: ctrl0); |
586 | if (ret) |
587 | return ret; |
588 | |
589 | ret = regmap_update_bits(map: adau1977->regmap, ADAU1977_REG_SAI_CTRL1, |
590 | ADAU1977_SAI_CTRL1_SLOT_WIDTH_MASK, val: ctrl1); |
591 | if (ret) |
592 | return ret; |
593 | |
594 | adau1977->slot_width = width; |
595 | |
596 | /* In clock provider mode the maximum bitclock is 24.576 MHz */ |
597 | adau1977->max_clock_provider_fs = min(192000, 24576000 / width / slots); |
598 | |
599 | return 0; |
600 | } |
601 | |
602 | static int adau1977_mute(struct snd_soc_dai *dai, int mute, int stream) |
603 | { |
604 | struct adau1977 *adau1977 = snd_soc_component_get_drvdata(c: dai->component); |
605 | unsigned int val; |
606 | |
607 | if (mute) |
608 | val = ADAU1977_MISC_CONTROL_MMUTE; |
609 | else |
610 | val = 0; |
611 | |
612 | return regmap_update_bits(map: adau1977->regmap, ADAU1977_REG_MISC_CONTROL, |
613 | ADAU1977_MISC_CONTROL_MMUTE, val); |
614 | } |
615 | |
616 | static int adau1977_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) |
617 | { |
618 | struct adau1977 *adau1977 = snd_soc_component_get_drvdata(c: dai->component); |
619 | unsigned int ctrl0 = 0, ctrl1 = 0, block_power = 0; |
620 | bool invert_lrclk; |
621 | int ret; |
622 | |
623 | switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) { |
624 | case SND_SOC_DAIFMT_CBC_CFC: |
625 | adau1977->clock_provider = false; |
626 | break; |
627 | case SND_SOC_DAIFMT_CBP_CFP: |
628 | ctrl1 |= ADAU1977_SAI_CTRL1_MASTER; |
629 | adau1977->clock_provider = true; |
630 | break; |
631 | default: |
632 | return -EINVAL; |
633 | } |
634 | |
635 | switch (fmt & SND_SOC_DAIFMT_INV_MASK) { |
636 | case SND_SOC_DAIFMT_NB_NF: |
637 | invert_lrclk = false; |
638 | break; |
639 | case SND_SOC_DAIFMT_IB_NF: |
640 | block_power |= ADAU1977_BLOCK_POWER_SAI_BCLK_EDGE; |
641 | invert_lrclk = false; |
642 | break; |
643 | case SND_SOC_DAIFMT_NB_IF: |
644 | invert_lrclk = true; |
645 | break; |
646 | case SND_SOC_DAIFMT_IB_IF: |
647 | block_power |= ADAU1977_BLOCK_POWER_SAI_BCLK_EDGE; |
648 | invert_lrclk = true; |
649 | break; |
650 | default: |
651 | return -EINVAL; |
652 | } |
653 | |
654 | adau1977->right_j = false; |
655 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { |
656 | case SND_SOC_DAIFMT_I2S: |
657 | ctrl0 |= ADAU1977_SAI_CTRL0_FMT_I2S; |
658 | break; |
659 | case SND_SOC_DAIFMT_LEFT_J: |
660 | ctrl0 |= ADAU1977_SAI_CTRL0_FMT_LJ; |
661 | invert_lrclk = !invert_lrclk; |
662 | break; |
663 | case SND_SOC_DAIFMT_RIGHT_J: |
664 | ctrl0 |= ADAU1977_SAI_CTRL0_FMT_RJ_24BIT; |
665 | adau1977->right_j = true; |
666 | invert_lrclk = !invert_lrclk; |
667 | break; |
668 | case SND_SOC_DAIFMT_DSP_A: |
669 | ctrl1 |= ADAU1977_SAI_CTRL1_LRCLK_PULSE; |
670 | ctrl0 |= ADAU1977_SAI_CTRL0_FMT_I2S; |
671 | invert_lrclk = false; |
672 | break; |
673 | case SND_SOC_DAIFMT_DSP_B: |
674 | ctrl1 |= ADAU1977_SAI_CTRL1_LRCLK_PULSE; |
675 | ctrl0 |= ADAU1977_SAI_CTRL0_FMT_LJ; |
676 | invert_lrclk = false; |
677 | break; |
678 | default: |
679 | return -EINVAL; |
680 | } |
681 | |
682 | if (invert_lrclk) |
683 | block_power |= ADAU1977_BLOCK_POWER_SAI_LR_POL; |
684 | |
685 | ret = regmap_update_bits(map: adau1977->regmap, ADAU1977_REG_BLOCK_POWER_SAI, |
686 | ADAU1977_BLOCK_POWER_SAI_LR_POL | |
687 | ADAU1977_BLOCK_POWER_SAI_BCLK_EDGE, val: block_power); |
688 | if (ret) |
689 | return ret; |
690 | |
691 | ret = regmap_update_bits(map: adau1977->regmap, ADAU1977_REG_SAI_CTRL0, |
692 | ADAU1977_SAI_CTRL0_FMT_MASK, |
693 | val: ctrl0); |
694 | if (ret) |
695 | return ret; |
696 | |
697 | return regmap_update_bits(map: adau1977->regmap, ADAU1977_REG_SAI_CTRL1, |
698 | ADAU1977_SAI_CTRL1_MASTER | ADAU1977_SAI_CTRL1_LRCLK_PULSE, |
699 | val: ctrl1); |
700 | } |
701 | |
702 | static int adau1977_startup(struct snd_pcm_substream *substream, |
703 | struct snd_soc_dai *dai) |
704 | { |
705 | struct adau1977 *adau1977 = snd_soc_component_get_drvdata(c: dai->component); |
706 | u64 formats = 0; |
707 | |
708 | if (adau1977->slot_width == 16) |
709 | formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE; |
710 | else if (adau1977->right_j || adau1977->slot_width == 24) |
711 | formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE | |
712 | SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S24_BE; |
713 | |
714 | snd_pcm_hw_constraint_list(runtime: substream->runtime, cond: 0, |
715 | SNDRV_PCM_HW_PARAM_RATE, l: &adau1977->constraints); |
716 | |
717 | if (adau1977->clock_provider) |
718 | snd_pcm_hw_constraint_minmax(runtime: substream->runtime, |
719 | SNDRV_PCM_HW_PARAM_RATE, min: 8000, |
720 | max: adau1977->max_clock_provider_fs); |
721 | |
722 | if (formats != 0) |
723 | snd_pcm_hw_constraint_mask64(runtime: substream->runtime, |
724 | SNDRV_PCM_HW_PARAM_FORMAT, mask: formats); |
725 | |
726 | return 0; |
727 | } |
728 | |
729 | static int adau1977_set_tristate(struct snd_soc_dai *dai, int tristate) |
730 | { |
731 | struct adau1977 *adau1977 = snd_soc_component_get_drvdata(c: dai->component); |
732 | unsigned int val; |
733 | |
734 | if (tristate) |
735 | val = ADAU1977_SAI_OVERTEMP_DRV_HIZ; |
736 | else |
737 | val = 0; |
738 | |
739 | return regmap_update_bits(map: adau1977->regmap, ADAU1977_REG_SAI_OVERTEMP, |
740 | ADAU1977_SAI_OVERTEMP_DRV_HIZ, val); |
741 | } |
742 | |
743 | static const struct snd_soc_dai_ops adau1977_dai_ops = { |
744 | .startup = adau1977_startup, |
745 | .hw_params = adau1977_hw_params, |
746 | .mute_stream = adau1977_mute, |
747 | .set_fmt = adau1977_set_dai_fmt, |
748 | .set_tdm_slot = adau1977_set_tdm_slot, |
749 | .set_tristate = adau1977_set_tristate, |
750 | }; |
751 | |
752 | static struct snd_soc_dai_driver adau1977_dai = { |
753 | .name = "adau1977-hifi" , |
754 | .capture = { |
755 | .stream_name = "Capture" , |
756 | .channels_min = 1, |
757 | .channels_max = 4, |
758 | .rates = SNDRV_PCM_RATE_KNOT, |
759 | .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE | |
760 | SNDRV_PCM_FMTBIT_S32_LE, |
761 | .sig_bits = 24, |
762 | }, |
763 | .ops = &adau1977_dai_ops, |
764 | }; |
765 | |
766 | static const unsigned int adau1977_rates[] = { |
767 | 8000, 16000, 32000, 64000, 128000, |
768 | 11025, 22050, 44100, 88200, 172400, |
769 | 12000, 24000, 48000, 96000, 192000, |
770 | }; |
771 | |
772 | #define ADAU1977_RATE_CONSTRAINT_MASK_32000 0x001f |
773 | #define ADAU1977_RATE_CONSTRAINT_MASK_44100 0x03e0 |
774 | #define ADAU1977_RATE_CONSTRAINT_MASK_48000 0x7c00 |
775 | /* All rates >= 32000 */ |
776 | #define ADAU1977_RATE_CONSTRAINT_MASK_LRCLK 0x739c |
777 | |
778 | static bool adau1977_check_sysclk(unsigned int mclk, unsigned int base_freq) |
779 | { |
780 | unsigned int mcs; |
781 | |
782 | if (mclk % (base_freq * 128) != 0) |
783 | return false; |
784 | |
785 | mcs = mclk / (128 * base_freq); |
786 | if (mcs < 1 || mcs > 6 || mcs == 5) |
787 | return false; |
788 | |
789 | return true; |
790 | } |
791 | |
792 | static int adau1977_set_sysclk(struct snd_soc_component *component, |
793 | int clk_id, int source, unsigned int freq, int dir) |
794 | { |
795 | struct adau1977 *adau1977 = snd_soc_component_get_drvdata(c: component); |
796 | unsigned int mask = 0; |
797 | unsigned int clk_src; |
798 | unsigned int ret; |
799 | |
800 | if (dir != SND_SOC_CLOCK_IN) |
801 | return -EINVAL; |
802 | |
803 | if (clk_id != ADAU1977_SYSCLK) |
804 | return -EINVAL; |
805 | |
806 | switch (source) { |
807 | case ADAU1977_SYSCLK_SRC_MCLK: |
808 | clk_src = 0; |
809 | break; |
810 | case ADAU1977_SYSCLK_SRC_LRCLK: |
811 | clk_src = ADAU1977_PLL_CLK_S; |
812 | break; |
813 | default: |
814 | return -EINVAL; |
815 | } |
816 | |
817 | if (freq != 0 && source == ADAU1977_SYSCLK_SRC_MCLK) { |
818 | if (freq < 4000000 || freq > 36864000) |
819 | return -EINVAL; |
820 | |
821 | if (adau1977_check_sysclk(mclk: freq, base_freq: 32000)) |
822 | mask |= ADAU1977_RATE_CONSTRAINT_MASK_32000; |
823 | if (adau1977_check_sysclk(mclk: freq, base_freq: 44100)) |
824 | mask |= ADAU1977_RATE_CONSTRAINT_MASK_44100; |
825 | if (adau1977_check_sysclk(mclk: freq, base_freq: 48000)) |
826 | mask |= ADAU1977_RATE_CONSTRAINT_MASK_48000; |
827 | |
828 | if (mask == 0) |
829 | return -EINVAL; |
830 | } else if (source == ADAU1977_SYSCLK_SRC_LRCLK) { |
831 | mask = ADAU1977_RATE_CONSTRAINT_MASK_LRCLK; |
832 | } |
833 | |
834 | ret = regmap_update_bits(map: adau1977->regmap, ADAU1977_REG_PLL, |
835 | ADAU1977_PLL_CLK_S, val: clk_src); |
836 | if (ret) |
837 | return ret; |
838 | |
839 | adau1977->constraints.mask = mask; |
840 | adau1977->sysclk_src = source; |
841 | adau1977->sysclk = freq; |
842 | |
843 | return 0; |
844 | } |
845 | |
846 | static int adau1977_component_probe(struct snd_soc_component *component) |
847 | { |
848 | struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component); |
849 | struct adau1977 *adau1977 = snd_soc_component_get_drvdata(c: component); |
850 | int ret; |
851 | |
852 | switch (adau1977->type) { |
853 | case ADAU1977: |
854 | ret = snd_soc_dapm_new_controls(dapm, |
855 | widget: adau1977_micbias_dapm_widgets, |
856 | ARRAY_SIZE(adau1977_micbias_dapm_widgets)); |
857 | if (ret < 0) |
858 | return ret; |
859 | break; |
860 | default: |
861 | break; |
862 | } |
863 | |
864 | return 0; |
865 | } |
866 | |
867 | static const struct snd_soc_component_driver adau1977_component_driver = { |
868 | .probe = adau1977_component_probe, |
869 | .set_bias_level = adau1977_set_bias_level, |
870 | .set_sysclk = adau1977_set_sysclk, |
871 | .controls = adau1977_snd_controls, |
872 | .num_controls = ARRAY_SIZE(adau1977_snd_controls), |
873 | .dapm_widgets = adau1977_dapm_widgets, |
874 | .num_dapm_widgets = ARRAY_SIZE(adau1977_dapm_widgets), |
875 | .dapm_routes = adau1977_dapm_routes, |
876 | .num_dapm_routes = ARRAY_SIZE(adau1977_dapm_routes), |
877 | .use_pmdown_time = 1, |
878 | .endianness = 1, |
879 | }; |
880 | |
881 | static int adau1977_setup_micbias(struct adau1977 *adau1977) |
882 | { |
883 | unsigned int micbias; |
884 | |
885 | if (device_property_read_u32(dev: adau1977->dev, propname: "adi,micbias" , val: &micbias)) |
886 | micbias = ADAU1977_MICBIAS_8V5; |
887 | |
888 | if (micbias > ADAU1977_MICBIAS_9V0) { |
889 | dev_err(adau1977->dev, "Invalid value for 'adi,micbias'\n" ); |
890 | return -EINVAL; |
891 | } |
892 | |
893 | return regmap_update_bits(map: adau1977->regmap, ADAU1977_REG_MICBIAS, |
894 | ADAU1977_MICBIAS_MB_VOLTS_MASK, |
895 | val: micbias << ADAU1977_MICBIAS_MB_VOLTS_OFFSET); |
896 | } |
897 | |
898 | int adau1977_probe(struct device *dev, struct regmap *regmap, |
899 | enum adau1977_type type, void (*switch_mode)(struct device *dev)) |
900 | { |
901 | unsigned int power_off_mask; |
902 | struct adau1977 *adau1977; |
903 | int ret; |
904 | |
905 | if (IS_ERR(ptr: regmap)) |
906 | return PTR_ERR(ptr: regmap); |
907 | |
908 | adau1977 = devm_kzalloc(dev, size: sizeof(*adau1977), GFP_KERNEL); |
909 | if (adau1977 == NULL) |
910 | return -ENOMEM; |
911 | |
912 | adau1977->dev = dev; |
913 | adau1977->type = type; |
914 | adau1977->regmap = regmap; |
915 | adau1977->switch_mode = switch_mode; |
916 | adau1977->max_clock_provider_fs = 192000; |
917 | |
918 | adau1977->constraints.list = adau1977_rates; |
919 | adau1977->constraints.count = ARRAY_SIZE(adau1977_rates); |
920 | |
921 | adau1977->avdd_reg = devm_regulator_get(dev, id: "AVDD" ); |
922 | if (IS_ERR(ptr: adau1977->avdd_reg)) |
923 | return PTR_ERR(ptr: adau1977->avdd_reg); |
924 | |
925 | adau1977->dvdd_reg = devm_regulator_get_optional(dev, id: "DVDD" ); |
926 | if (IS_ERR(ptr: adau1977->dvdd_reg)) { |
927 | if (PTR_ERR(ptr: adau1977->dvdd_reg) != -ENODEV) |
928 | return PTR_ERR(ptr: adau1977->dvdd_reg); |
929 | adau1977->dvdd_reg = NULL; |
930 | } |
931 | |
932 | adau1977->reset_gpio = devm_gpiod_get_optional(dev, con_id: "reset" , |
933 | flags: GPIOD_OUT_LOW); |
934 | if (IS_ERR(ptr: adau1977->reset_gpio)) |
935 | return PTR_ERR(ptr: adau1977->reset_gpio); |
936 | |
937 | dev_set_drvdata(dev, data: adau1977); |
938 | |
939 | if (adau1977->reset_gpio) |
940 | ndelay(100); |
941 | |
942 | ret = adau1977_power_enable(adau1977); |
943 | if (ret) |
944 | return ret; |
945 | |
946 | if (type == ADAU1977) { |
947 | ret = adau1977_setup_micbias(adau1977); |
948 | if (ret) |
949 | goto err_poweroff; |
950 | } |
951 | |
952 | if (adau1977->dvdd_reg) |
953 | power_off_mask = ~0; |
954 | else |
955 | power_off_mask = (unsigned int)~ADAU1977_BLOCK_POWER_SAI_LDO_EN; |
956 | |
957 | ret = regmap_update_bits(map: adau1977->regmap, ADAU1977_REG_BLOCK_POWER_SAI, |
958 | mask: power_off_mask, val: 0x00); |
959 | if (ret) |
960 | goto err_poweroff; |
961 | |
962 | ret = adau1977_power_disable(adau1977); |
963 | if (ret) |
964 | return ret; |
965 | |
966 | return devm_snd_soc_register_component(dev, component_driver: &adau1977_component_driver, |
967 | dai_drv: &adau1977_dai, num_dai: 1); |
968 | |
969 | err_poweroff: |
970 | adau1977_power_disable(adau1977); |
971 | return ret; |
972 | |
973 | } |
974 | EXPORT_SYMBOL_GPL(adau1977_probe); |
975 | |
976 | static bool adau1977_register_volatile(struct device *dev, unsigned int reg) |
977 | { |
978 | switch (reg) { |
979 | case ADAU1977_REG_STATUS(0): |
980 | case ADAU1977_REG_STATUS(1): |
981 | case ADAU1977_REG_STATUS(2): |
982 | case ADAU1977_REG_STATUS(3): |
983 | case ADAU1977_REG_ADC_CLIP: |
984 | return true; |
985 | } |
986 | |
987 | return false; |
988 | } |
989 | |
990 | const struct regmap_config adau1977_regmap_config = { |
991 | .max_register = ADAU1977_REG_DC_HPF_CAL, |
992 | .volatile_reg = adau1977_register_volatile, |
993 | |
994 | .cache_type = REGCACHE_MAPLE, |
995 | .reg_defaults = adau1977_reg_defaults, |
996 | .num_reg_defaults = ARRAY_SIZE(adau1977_reg_defaults), |
997 | }; |
998 | EXPORT_SYMBOL_GPL(adau1977_regmap_config); |
999 | |
1000 | MODULE_DESCRIPTION("ASoC ADAU1977/ADAU1978/ADAU1979 driver" ); |
1001 | MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>" ); |
1002 | MODULE_LICENSE("GPL" ); |
1003 | |