1 | // SPDX-License-Identifier: GPL-2.0 |
2 | // |
3 | // Audio driver for AK5558 ADC |
4 | // |
5 | // Copyright (C) 2015 Asahi Kasei Microdevices Corporation |
6 | // Copyright 2018 NXP |
7 | |
8 | #include <linux/delay.h> |
9 | #include <linux/gpio/consumer.h> |
10 | #include <linux/i2c.h> |
11 | #include <linux/module.h> |
12 | #include <linux/of.h> |
13 | #include <linux/pm_runtime.h> |
14 | #include <linux/regmap.h> |
15 | #include <linux/regulator/consumer.h> |
16 | #include <linux/slab.h> |
17 | |
18 | #include <sound/initval.h> |
19 | #include <sound/pcm.h> |
20 | #include <sound/pcm_params.h> |
21 | #include <sound/soc.h> |
22 | #include <sound/soc-dapm.h> |
23 | #include <sound/tlv.h> |
24 | |
25 | #include "ak5558.h" |
26 | |
27 | enum ak555x_type { |
28 | AK5558, |
29 | AK5552, |
30 | }; |
31 | |
32 | #define AK5558_NUM_SUPPLIES 2 |
33 | static const char *ak5558_supply_names[AK5558_NUM_SUPPLIES] = { |
34 | "DVDD" , |
35 | "AVDD" , |
36 | }; |
37 | |
38 | /* AK5558 Codec Private Data */ |
39 | struct ak5558_priv { |
40 | struct regulator_bulk_data supplies[AK5558_NUM_SUPPLIES]; |
41 | struct snd_soc_component component; |
42 | struct regmap *regmap; |
43 | struct i2c_client *i2c; |
44 | struct gpio_desc *reset_gpiod; /* Reset & Power down GPIO */ |
45 | int slots; |
46 | int slot_width; |
47 | }; |
48 | |
49 | /* ak5558 register cache & default register settings */ |
50 | static const struct reg_default ak5558_reg[] = { |
51 | { 0x0, 0xFF }, /* 0x00 AK5558_00_POWER_MANAGEMENT1 */ |
52 | { 0x1, 0x01 }, /* 0x01 AK5558_01_POWER_MANAGEMENT2 */ |
53 | { 0x2, 0x01 }, /* 0x02 AK5558_02_CONTROL1 */ |
54 | { 0x3, 0x00 }, /* 0x03 AK5558_03_CONTROL2 */ |
55 | { 0x4, 0x00 }, /* 0x04 AK5558_04_CONTROL3 */ |
56 | { 0x5, 0x00 } /* 0x05 AK5558_05_DSD */ |
57 | }; |
58 | |
59 | static const char * const mono_texts[] = { |
60 | "8 Slot" , "2 Slot" , "4 Slot" , "1 Slot" , |
61 | }; |
62 | |
63 | static const struct soc_enum ak5558_mono_enum[] = { |
64 | SOC_ENUM_SINGLE(AK5558_01_POWER_MANAGEMENT2, 1, |
65 | ARRAY_SIZE(mono_texts), mono_texts), |
66 | }; |
67 | |
68 | static const char * const mono_5552_texts[] = { |
69 | "2 Slot" , "1 Slot (Fixed)" , "2 Slot" , "1 Slot (Optimal)" , |
70 | }; |
71 | |
72 | static const struct soc_enum ak5552_mono_enum[] = { |
73 | SOC_ENUM_SINGLE(AK5558_01_POWER_MANAGEMENT2, 1, |
74 | ARRAY_SIZE(mono_5552_texts), mono_5552_texts), |
75 | }; |
76 | |
77 | static const char * const digfil_texts[] = { |
78 | "Sharp Roll-Off" , "Slow Roll-Off" , |
79 | "Short Delay Sharp Roll-Off" , "Short Delay Slow Roll-Off" , |
80 | }; |
81 | |
82 | static const struct soc_enum ak5558_adcset_enum[] = { |
83 | SOC_ENUM_SINGLE(AK5558_04_CONTROL3, 0, |
84 | ARRAY_SIZE(digfil_texts), digfil_texts), |
85 | }; |
86 | |
87 | static const struct snd_kcontrol_new ak5558_snd_controls[] = { |
88 | SOC_ENUM("Monaural Mode" , ak5558_mono_enum[0]), |
89 | SOC_ENUM("Digital Filter" , ak5558_adcset_enum[0]), |
90 | }; |
91 | |
92 | static const struct snd_kcontrol_new ak5552_snd_controls[] = { |
93 | SOC_ENUM("Monaural Mode" , ak5552_mono_enum[0]), |
94 | SOC_ENUM("Digital Filter" , ak5558_adcset_enum[0]), |
95 | }; |
96 | |
97 | static const struct snd_soc_dapm_widget ak5558_dapm_widgets[] = { |
98 | /* Analog Input */ |
99 | SND_SOC_DAPM_INPUT("AIN1" ), |
100 | SND_SOC_DAPM_INPUT("AIN2" ), |
101 | SND_SOC_DAPM_INPUT("AIN3" ), |
102 | SND_SOC_DAPM_INPUT("AIN4" ), |
103 | SND_SOC_DAPM_INPUT("AIN5" ), |
104 | SND_SOC_DAPM_INPUT("AIN6" ), |
105 | SND_SOC_DAPM_INPUT("AIN7" ), |
106 | SND_SOC_DAPM_INPUT("AIN8" ), |
107 | |
108 | SND_SOC_DAPM_ADC("ADC Ch1" , NULL, AK5558_00_POWER_MANAGEMENT1, 0, 0), |
109 | SND_SOC_DAPM_ADC("ADC Ch2" , NULL, AK5558_00_POWER_MANAGEMENT1, 1, 0), |
110 | SND_SOC_DAPM_ADC("ADC Ch3" , NULL, AK5558_00_POWER_MANAGEMENT1, 2, 0), |
111 | SND_SOC_DAPM_ADC("ADC Ch4" , NULL, AK5558_00_POWER_MANAGEMENT1, 3, 0), |
112 | SND_SOC_DAPM_ADC("ADC Ch5" , NULL, AK5558_00_POWER_MANAGEMENT1, 4, 0), |
113 | SND_SOC_DAPM_ADC("ADC Ch6" , NULL, AK5558_00_POWER_MANAGEMENT1, 5, 0), |
114 | SND_SOC_DAPM_ADC("ADC Ch7" , NULL, AK5558_00_POWER_MANAGEMENT1, 6, 0), |
115 | SND_SOC_DAPM_ADC("ADC Ch8" , NULL, AK5558_00_POWER_MANAGEMENT1, 7, 0), |
116 | |
117 | SND_SOC_DAPM_AIF_OUT("SDTO" , "Capture" , 0, SND_SOC_NOPM, 0, 0), |
118 | }; |
119 | |
120 | static const struct snd_soc_dapm_widget ak5552_dapm_widgets[] = { |
121 | /* Analog Input */ |
122 | SND_SOC_DAPM_INPUT("AIN1" ), |
123 | SND_SOC_DAPM_INPUT("AIN2" ), |
124 | |
125 | SND_SOC_DAPM_ADC("ADC Ch1" , NULL, AK5558_00_POWER_MANAGEMENT1, 0, 0), |
126 | SND_SOC_DAPM_ADC("ADC Ch2" , NULL, AK5558_00_POWER_MANAGEMENT1, 1, 0), |
127 | |
128 | SND_SOC_DAPM_AIF_OUT("SDTO" , "Capture" , 0, SND_SOC_NOPM, 0, 0), |
129 | }; |
130 | |
131 | static const struct snd_soc_dapm_route ak5558_intercon[] = { |
132 | {"ADC Ch1" , NULL, "AIN1" }, |
133 | {"SDTO" , NULL, "ADC Ch1" }, |
134 | |
135 | {"ADC Ch2" , NULL, "AIN2" }, |
136 | {"SDTO" , NULL, "ADC Ch2" }, |
137 | |
138 | {"ADC Ch3" , NULL, "AIN3" }, |
139 | {"SDTO" , NULL, "ADC Ch3" }, |
140 | |
141 | {"ADC Ch4" , NULL, "AIN4" }, |
142 | {"SDTO" , NULL, "ADC Ch4" }, |
143 | |
144 | {"ADC Ch5" , NULL, "AIN5" }, |
145 | {"SDTO" , NULL, "ADC Ch5" }, |
146 | |
147 | {"ADC Ch6" , NULL, "AIN6" }, |
148 | {"SDTO" , NULL, "ADC Ch6" }, |
149 | |
150 | {"ADC Ch7" , NULL, "AIN7" }, |
151 | {"SDTO" , NULL, "ADC Ch7" }, |
152 | |
153 | {"ADC Ch8" , NULL, "AIN8" }, |
154 | {"SDTO" , NULL, "ADC Ch8" }, |
155 | }; |
156 | |
157 | static const struct snd_soc_dapm_route ak5552_intercon[] = { |
158 | {"ADC Ch1" , NULL, "AIN1" }, |
159 | {"SDTO" , NULL, "ADC Ch1" }, |
160 | |
161 | {"ADC Ch2" , NULL, "AIN2" }, |
162 | {"SDTO" , NULL, "ADC Ch2" }, |
163 | }; |
164 | |
165 | static int ak5558_set_mcki(struct snd_soc_component *component) |
166 | { |
167 | return snd_soc_component_update_bits(component, AK5558_02_CONTROL1, AK5558_CKS, |
168 | AK5558_CKS_AUTO); |
169 | } |
170 | |
171 | static int ak5558_hw_params(struct snd_pcm_substream *substream, |
172 | struct snd_pcm_hw_params *params, |
173 | struct snd_soc_dai *dai) |
174 | { |
175 | struct snd_soc_component *component = dai->component; |
176 | struct ak5558_priv *ak5558 = snd_soc_component_get_drvdata(c: component); |
177 | u8 bits; |
178 | int pcm_width = max(params_physical_width(params), ak5558->slot_width); |
179 | |
180 | switch (pcm_width) { |
181 | case 16: |
182 | bits = AK5558_DIF_24BIT_MODE; |
183 | break; |
184 | case 32: |
185 | bits = AK5558_DIF_32BIT_MODE; |
186 | break; |
187 | default: |
188 | return -EINVAL; |
189 | } |
190 | |
191 | snd_soc_component_update_bits(component, AK5558_02_CONTROL1, AK5558_BITS, val: bits); |
192 | |
193 | return 0; |
194 | } |
195 | |
196 | static int ak5558_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) |
197 | { |
198 | struct snd_soc_component *component = dai->component; |
199 | u8 format; |
200 | |
201 | switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) { |
202 | case SND_SOC_DAIFMT_CBC_CFC: |
203 | break; |
204 | case SND_SOC_DAIFMT_CBP_CFP: |
205 | break; |
206 | case SND_SOC_DAIFMT_CBC_CFP: |
207 | case SND_SOC_DAIFMT_CBP_CFC: |
208 | default: |
209 | dev_err(dai->dev, "Clock mode unsupported" ); |
210 | return -EINVAL; |
211 | } |
212 | |
213 | /* set master/slave audio interface */ |
214 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { |
215 | case SND_SOC_DAIFMT_I2S: |
216 | format = AK5558_DIF_I2S_MODE; |
217 | break; |
218 | case SND_SOC_DAIFMT_LEFT_J: |
219 | format = AK5558_DIF_MSB_MODE; |
220 | break; |
221 | case SND_SOC_DAIFMT_DSP_B: |
222 | format = AK5558_DIF_MSB_MODE; |
223 | break; |
224 | default: |
225 | return -EINVAL; |
226 | } |
227 | |
228 | snd_soc_component_update_bits(component, AK5558_02_CONTROL1, AK5558_DIF, val: format); |
229 | |
230 | return 0; |
231 | } |
232 | |
233 | static int ak5558_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask, |
234 | unsigned int rx_mask, int slots, |
235 | int slot_width) |
236 | { |
237 | struct snd_soc_component *component = dai->component; |
238 | struct ak5558_priv *ak5558 = snd_soc_component_get_drvdata(c: component); |
239 | int tdm_mode; |
240 | |
241 | ak5558->slots = slots; |
242 | ak5558->slot_width = slot_width; |
243 | |
244 | switch (slots * slot_width) { |
245 | case 128: |
246 | tdm_mode = AK5558_MODE_TDM128; |
247 | break; |
248 | case 256: |
249 | tdm_mode = AK5558_MODE_TDM256; |
250 | break; |
251 | case 512: |
252 | tdm_mode = AK5558_MODE_TDM512; |
253 | break; |
254 | default: |
255 | tdm_mode = AK5558_MODE_NORMAL; |
256 | break; |
257 | } |
258 | |
259 | snd_soc_component_update_bits(component, AK5558_03_CONTROL2, AK5558_MODE_BITS, |
260 | val: tdm_mode); |
261 | return 0; |
262 | } |
263 | |
264 | #define AK5558_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\ |
265 | SNDRV_PCM_FMTBIT_S24_LE |\ |
266 | SNDRV_PCM_FMTBIT_S32_LE) |
267 | |
268 | static const unsigned int ak5558_rates[] = { |
269 | 8000, 11025, 16000, 22050, |
270 | 32000, 44100, 48000, 88200, |
271 | 96000, 176400, 192000, 352800, |
272 | 384000, 705600, 768000, 1411200, |
273 | 2822400, |
274 | }; |
275 | |
276 | static const struct snd_pcm_hw_constraint_list ak5558_rate_constraints = { |
277 | .count = ARRAY_SIZE(ak5558_rates), |
278 | .list = ak5558_rates, |
279 | }; |
280 | |
281 | static int ak5558_startup(struct snd_pcm_substream *substream, |
282 | struct snd_soc_dai *dai) |
283 | { |
284 | return snd_pcm_hw_constraint_list(runtime: substream->runtime, cond: 0, |
285 | SNDRV_PCM_HW_PARAM_RATE, |
286 | l: &ak5558_rate_constraints); |
287 | } |
288 | |
289 | static const struct snd_soc_dai_ops ak5558_dai_ops = { |
290 | .startup = ak5558_startup, |
291 | .hw_params = ak5558_hw_params, |
292 | |
293 | .set_fmt = ak5558_set_dai_fmt, |
294 | .set_tdm_slot = ak5558_set_tdm_slot, |
295 | }; |
296 | |
297 | static struct snd_soc_dai_driver ak5558_dai = { |
298 | .name = "ak5558-aif" , |
299 | .capture = { |
300 | .stream_name = "Capture" , |
301 | .channels_min = 1, |
302 | .channels_max = 8, |
303 | .rates = SNDRV_PCM_RATE_KNOT, |
304 | .formats = AK5558_FORMATS, |
305 | }, |
306 | .ops = &ak5558_dai_ops, |
307 | }; |
308 | |
309 | static struct snd_soc_dai_driver ak5552_dai = { |
310 | .name = "ak5552-aif" , |
311 | .capture = { |
312 | .stream_name = "Capture" , |
313 | .channels_min = 1, |
314 | .channels_max = 2, |
315 | .rates = SNDRV_PCM_RATE_KNOT, |
316 | .formats = AK5558_FORMATS, |
317 | }, |
318 | .ops = &ak5558_dai_ops, |
319 | }; |
320 | |
321 | static void ak5558_reset(struct ak5558_priv *ak5558, bool active) |
322 | { |
323 | if (!ak5558->reset_gpiod) |
324 | return; |
325 | |
326 | gpiod_set_value_cansleep(desc: ak5558->reset_gpiod, value: active); |
327 | usleep_range(min: 1000, max: 2000); |
328 | } |
329 | |
330 | static int ak5558_probe(struct snd_soc_component *component) |
331 | { |
332 | struct ak5558_priv *ak5558 = snd_soc_component_get_drvdata(c: component); |
333 | |
334 | ak5558_reset(ak5558, active: false); |
335 | return ak5558_set_mcki(component); |
336 | } |
337 | |
338 | static void ak5558_remove(struct snd_soc_component *component) |
339 | { |
340 | struct ak5558_priv *ak5558 = snd_soc_component_get_drvdata(c: component); |
341 | |
342 | ak5558_reset(ak5558, active: true); |
343 | } |
344 | |
345 | static int __maybe_unused ak5558_runtime_suspend(struct device *dev) |
346 | { |
347 | struct ak5558_priv *ak5558 = dev_get_drvdata(dev); |
348 | |
349 | regcache_cache_only(map: ak5558->regmap, enable: true); |
350 | ak5558_reset(ak5558, active: true); |
351 | |
352 | regulator_bulk_disable(ARRAY_SIZE(ak5558->supplies), |
353 | consumers: ak5558->supplies); |
354 | return 0; |
355 | } |
356 | |
357 | static int __maybe_unused ak5558_runtime_resume(struct device *dev) |
358 | { |
359 | struct ak5558_priv *ak5558 = dev_get_drvdata(dev); |
360 | int ret; |
361 | |
362 | ret = regulator_bulk_enable(ARRAY_SIZE(ak5558->supplies), |
363 | consumers: ak5558->supplies); |
364 | if (ret != 0) { |
365 | dev_err(dev, "Failed to enable supplies: %d\n" , ret); |
366 | return ret; |
367 | } |
368 | |
369 | ak5558_reset(ak5558, active: true); |
370 | ak5558_reset(ak5558, active: false); |
371 | |
372 | regcache_cache_only(map: ak5558->regmap, enable: false); |
373 | regcache_mark_dirty(map: ak5558->regmap); |
374 | |
375 | return regcache_sync(map: ak5558->regmap); |
376 | } |
377 | |
378 | static const struct dev_pm_ops ak5558_pm = { |
379 | SET_RUNTIME_PM_OPS(ak5558_runtime_suspend, ak5558_runtime_resume, NULL) |
380 | SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, |
381 | pm_runtime_force_resume) |
382 | }; |
383 | |
384 | static const struct snd_soc_component_driver soc_codec_dev_ak5558 = { |
385 | .probe = ak5558_probe, |
386 | .remove = ak5558_remove, |
387 | .controls = ak5558_snd_controls, |
388 | .num_controls = ARRAY_SIZE(ak5558_snd_controls), |
389 | .dapm_widgets = ak5558_dapm_widgets, |
390 | .num_dapm_widgets = ARRAY_SIZE(ak5558_dapm_widgets), |
391 | .dapm_routes = ak5558_intercon, |
392 | .num_dapm_routes = ARRAY_SIZE(ak5558_intercon), |
393 | .idle_bias_on = 1, |
394 | .use_pmdown_time = 1, |
395 | .endianness = 1, |
396 | }; |
397 | |
398 | static const struct snd_soc_component_driver soc_codec_dev_ak5552 = { |
399 | .probe = ak5558_probe, |
400 | .remove = ak5558_remove, |
401 | .controls = ak5552_snd_controls, |
402 | .num_controls = ARRAY_SIZE(ak5552_snd_controls), |
403 | .dapm_widgets = ak5552_dapm_widgets, |
404 | .num_dapm_widgets = ARRAY_SIZE(ak5552_dapm_widgets), |
405 | .dapm_routes = ak5552_intercon, |
406 | .num_dapm_routes = ARRAY_SIZE(ak5552_intercon), |
407 | .idle_bias_on = 1, |
408 | .use_pmdown_time = 1, |
409 | .endianness = 1, |
410 | }; |
411 | |
412 | static const struct regmap_config ak5558_regmap = { |
413 | .reg_bits = 8, |
414 | .val_bits = 8, |
415 | |
416 | .max_register = AK5558_05_DSD, |
417 | .reg_defaults = ak5558_reg, |
418 | .num_reg_defaults = ARRAY_SIZE(ak5558_reg), |
419 | .cache_type = REGCACHE_RBTREE, |
420 | }; |
421 | |
422 | static int ak5558_i2c_probe(struct i2c_client *i2c) |
423 | { |
424 | struct ak5558_priv *ak5558; |
425 | int ret = 0; |
426 | int dev_id; |
427 | int i; |
428 | |
429 | ak5558 = devm_kzalloc(dev: &i2c->dev, size: sizeof(*ak5558), GFP_KERNEL); |
430 | if (!ak5558) |
431 | return -ENOMEM; |
432 | |
433 | ak5558->regmap = devm_regmap_init_i2c(i2c, &ak5558_regmap); |
434 | if (IS_ERR(ptr: ak5558->regmap)) |
435 | return PTR_ERR(ptr: ak5558->regmap); |
436 | |
437 | i2c_set_clientdata(client: i2c, data: ak5558); |
438 | ak5558->i2c = i2c; |
439 | |
440 | ak5558->reset_gpiod = devm_gpiod_get_optional(dev: &i2c->dev, con_id: "reset" , |
441 | flags: GPIOD_OUT_LOW); |
442 | if (IS_ERR(ptr: ak5558->reset_gpiod)) |
443 | return PTR_ERR(ptr: ak5558->reset_gpiod); |
444 | |
445 | for (i = 0; i < ARRAY_SIZE(ak5558->supplies); i++) |
446 | ak5558->supplies[i].supply = ak5558_supply_names[i]; |
447 | |
448 | ret = devm_regulator_bulk_get(dev: &i2c->dev, ARRAY_SIZE(ak5558->supplies), |
449 | consumers: ak5558->supplies); |
450 | if (ret != 0) { |
451 | dev_err(&i2c->dev, "Failed to request supplies: %d\n" , ret); |
452 | return ret; |
453 | } |
454 | |
455 | dev_id = (uintptr_t)of_device_get_match_data(dev: &i2c->dev); |
456 | switch (dev_id) { |
457 | case AK5552: |
458 | ret = devm_snd_soc_register_component(dev: &i2c->dev, |
459 | component_driver: &soc_codec_dev_ak5552, |
460 | dai_drv: &ak5552_dai, num_dai: 1); |
461 | break; |
462 | case AK5558: |
463 | ret = devm_snd_soc_register_component(dev: &i2c->dev, |
464 | component_driver: &soc_codec_dev_ak5558, |
465 | dai_drv: &ak5558_dai, num_dai: 1); |
466 | break; |
467 | default: |
468 | dev_err(&i2c->dev, "unexpected device type\n" ); |
469 | return -EINVAL; |
470 | } |
471 | if (ret < 0) { |
472 | dev_err(&i2c->dev, "failed to register component: %d\n" , ret); |
473 | return ret; |
474 | } |
475 | |
476 | pm_runtime_enable(dev: &i2c->dev); |
477 | regcache_cache_only(map: ak5558->regmap, enable: true); |
478 | |
479 | return 0; |
480 | } |
481 | |
482 | static void ak5558_i2c_remove(struct i2c_client *i2c) |
483 | { |
484 | pm_runtime_disable(dev: &i2c->dev); |
485 | } |
486 | |
487 | static const struct of_device_id ak5558_i2c_dt_ids[] __maybe_unused = { |
488 | { .compatible = "asahi-kasei,ak5558" , .data = (void *) AK5558 }, |
489 | { .compatible = "asahi-kasei,ak5552" , .data = (void *) AK5552 }, |
490 | { } |
491 | }; |
492 | MODULE_DEVICE_TABLE(of, ak5558_i2c_dt_ids); |
493 | |
494 | static struct i2c_driver ak5558_i2c_driver = { |
495 | .driver = { |
496 | .name = "ak5558" , |
497 | .of_match_table = of_match_ptr(ak5558_i2c_dt_ids), |
498 | .pm = &ak5558_pm, |
499 | }, |
500 | .probe = ak5558_i2c_probe, |
501 | .remove = ak5558_i2c_remove, |
502 | }; |
503 | |
504 | module_i2c_driver(ak5558_i2c_driver); |
505 | |
506 | MODULE_AUTHOR("Junichi Wakasugi <wakasugi.jb@om.asahi-kasei.co.jp>" ); |
507 | MODULE_AUTHOR("Mihai Serban <mihai.serban@nxp.com>" ); |
508 | MODULE_DESCRIPTION("ASoC AK5558 ADC driver" ); |
509 | MODULE_LICENSE("GPL v2" ); |
510 | |