ce05bc2172cb77d994b2350ed5e6cb115ea8b954
1 /*
2 ** =============================================================================
3 ** Copyright (c) 2016 Texas Instruments Inc.
4 **
5 ** This program is free software; you can redistribute it and/or modify it under
6 ** the terms of the GNU General Public License as published by the Free Software
7 ** Foundation; version 2.
8 **
9 ** This program is distributed in the hope that it will be useful, but WITHOUT
10 ** ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11 ** FOR A PARTICULAR PURPOSE.See the GNU General Public License for more details.
12 **
13 ** File:
14 ** tas2770-codec.c
15 **
16 ** Description:
17 ** ALSA SoC driver for TAS2770 20-W Digital Input Mono Class-D Audio Amplifier
18 ** with Speaker I/V Sense
19 **
20 ** =============================================================================
21 */
23 #ifdef CONFIG_TAS2770_CODEC
24 #define DEBUG
25 #include <linux/module.h>
26 #include <linux/moduleparam.h>
27 #include <linux/init.h>
28 #include <linux/delay.h>
29 #include <linux/pm.h>
30 #include <linux/i2c.h>
31 #include <linux/gpio.h>
32 #include <linux/regulator/consumer.h>
33 #include <linux/firmware.h>
34 #include <linux/regmap.h>
35 #include <linux/of.h>
36 #include <linux/of_gpio.h>
37 #include <linux/slab.h>
38 #include <sound/core.h>
39 #include <sound/pcm.h>
40 #include <sound/pcm_params.h>
41 #include <sound/soc.h>
42 #include <sound/initval.h>
43 #include <sound/tlv.h>
45 #include "tas2770.h"
48 #define TAS2770_MDELAY 0xFFFFFFFE
50 static int tas2770_set_slot(struct snd_soc_codec *codec, int slot_width);
52 static unsigned int tas2770_codec_read(struct snd_soc_codec *codec,
53 unsigned int reg)
54 {
55 struct tas2770_priv *pTAS2770 = snd_soc_codec_get_drvdata(codec);
56 int nResult = 0;
57 unsigned int value = 0;
59 mutex_lock(&pTAS2770->dev_lock);
61 nResult = regmap_read(pTAS2770->regmap, reg, &value);
63 if (nResult < 0)
64 dev_err(pTAS2770->dev, "%s, ERROR, reg=0x%x, E=%d\n",
65 __func__, reg, nResult);
66 else
67 dev_dbg(pTAS2770->dev, "%s, reg: 0x%x, value: 0x%x\n",
68 __func__, reg, value);
70 mutex_unlock(&pTAS2770->dev_lock);
72 if (nResult >= 0)
73 return value;
74 else
75 return nResult;
76 }
79 static int tas2770_codec_write(struct snd_soc_codec *codec, unsigned int reg,
80 unsigned int value)
81 {
82 struct tas2770_priv *pTAS2770 = snd_soc_codec_get_drvdata(codec);
84 int nResult = 0;
86 mutex_lock(&pTAS2770->dev_lock);
88 nResult = regmap_write(pTAS2770->regmap, reg, value);
89 if (nResult < 0)
90 dev_err(pTAS2770->dev, "%s, ERROR, reg=0x%x, E=%d\n",
91 __func__, reg, nResult);
92 else
93 dev_dbg(pTAS2770->dev, "%s, reg: 0x%x, 0x%x\n",
94 __func__, reg, value);
96 mutex_unlock(&pTAS2770->dev_lock);
98 return nResult;
100 }
103 static int tas2770_codec_suspend(struct snd_soc_codec *codec)
104 {
105 struct tas2770_priv *pTAS2770 = snd_soc_codec_get_drvdata(codec);
106 int ret = 0;
108 mutex_lock(&pTAS2770->codec_lock);
110 dev_dbg(pTAS2770->dev, "%s\n", __func__);
112 mutex_unlock(&pTAS2770->codec_lock);
113 return ret;
114 }
116 static int tas2770_codec_resume(struct snd_soc_codec *codec)
117 {
118 struct tas2770_priv *pTAS2770 = snd_soc_codec_get_drvdata(codec);
119 int ret = 0;
121 mutex_lock(&pTAS2770->codec_lock);
123 dev_dbg(pTAS2770->dev, "%s\n", __func__);
125 mutex_unlock(&pTAS2770->codec_lock);
126 return ret;
127 }
129 static const char * const tas2770_ASI1_src[] = {
130 "I2C offset", "Left", "Right", "LeftRightDiv2",
131 };
133 static SOC_ENUM_SINGLE_DECL(
134 tas2770_ASI1_src_enum, TAS2770_TDMConfigurationReg2,
135 4, tas2770_ASI1_src);
137 static const struct snd_kcontrol_new tas2770_asi1_mux =
138 SOC_DAPM_ENUM("ASI1 Source", tas2770_ASI1_src_enum);
141 static int tas2770_dac_event(struct snd_soc_dapm_widget *w,
142 struct snd_kcontrol *kcontrol, int event)
143 {
144 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
146 switch (event) {
147 case SND_SOC_DAPM_POST_PMU:
148 snd_soc_update_bits(codec, TAS2770_PowerControl,
149 TAS2770_PowerControl_OperationalMode10_Mask,
150 TAS2770_PowerControl_OperationalMode10_Mute);
151 break;
152 case SND_SOC_DAPM_PRE_PMD:
153 snd_soc_update_bits(codec, TAS2770_PowerControl,
154 TAS2770_PowerControl_OperationalMode10_Mask,
155 TAS2770_PowerControl_OperationalMode10_Shutdown);
156 break;
158 }
159 return 0;
161 }
163 static const struct snd_kcontrol_new isense_switch =
164 SOC_DAPM_SINGLE("Switch", TAS2770_PowerControl, 3, 1, 1);
165 static const struct snd_kcontrol_new vsense_switch =
166 SOC_DAPM_SINGLE("Switch", TAS2770_PowerControl, 2, 1, 1);
168 static const struct snd_soc_dapm_widget tas2770_dapm_widgets[] = {
169 SND_SOC_DAPM_AIF_IN("ASI1", "ASI1 Playback", 0, SND_SOC_NOPM, 0, 0),
170 SND_SOC_DAPM_MUX("ASI1 Sel", SND_SOC_NOPM, 0, 0,
171 &tas2770_asi1_mux),
172 SND_SOC_DAPM_SWITCH("ISENSE", TAS2770_PowerControl, 3, 1,
173 &isense_switch),
174 SND_SOC_DAPM_SWITCH("VSENSE", TAS2770_PowerControl, 2, 1,
175 &vsense_switch),
176 SND_SOC_DAPM_DAC_E("DAC", NULL, SND_SOC_NOPM, 0, 0, tas2770_dac_event,
177 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
178 SND_SOC_DAPM_OUTPUT("OUT"),
179 SND_SOC_DAPM_SIGGEN("VMON"),
180 SND_SOC_DAPM_SIGGEN("IMON")
181 };
183 static const struct snd_soc_dapm_route tas2770_audio_map[] = {
184 {"ASI1 Sel", "I2C offset", "ASI1"},
185 {"ASI1 Sel", "Left", "ASI1"},
186 {"ASI1 Sel", "Right", "ASI1"},
187 {"ASI1 Sel", "LeftRightDiv2", "ASI1"},
188 {"DAC", NULL, "ASI1 Sel"},
189 {"OUT", NULL, "DAC"},
190 {"ISENSE", "Switch", "IMON"},
191 {"VSENSE", "Switch", "VMON"},
192 };
195 static int tas2770_mute(struct snd_soc_dai *dai, int mute)
196 {
197 struct snd_soc_codec *codec = dai->codec;
198 struct tas2770_priv *pTAS2770 = snd_soc_codec_get_drvdata(codec);
199 dev_dbg(pTAS2770->dev, "%s\n", __func__);
201 mutex_lock(&pTAS2770->codec_lock);
202 if (mute) {
203 snd_soc_update_bits(codec, TAS2770_PowerControl,
204 TAS2770_PowerControl_OperationalMode10_Mask,
205 TAS2770_PowerControl_OperationalMode10_Mute);
206 } else {
207 snd_soc_update_bits(codec, TAS2770_PowerControl,
208 TAS2770_PowerControl_OperationalMode10_Mask,
209 TAS2770_PowerControl_OperationalMode10_Active);
210 }
211 mutex_unlock(&pTAS2770->codec_lock);
212 return 0;
213 }
215 static int tas2770_hw_params(struct snd_pcm_substream *substream,
216 struct snd_pcm_hw_params *params,
217 struct snd_soc_dai *dai)
218 {
219 struct snd_soc_codec *codec = dai->codec;
220 struct tas2770_priv *pTAS2770 = snd_soc_codec_get_drvdata(codec);
221 int ret = 0;
222 int slot_width_tmp = 16;
224 dev_dbg(pTAS2770->dev, "%s, format: %d\n", __func__,
225 params_format(params));
227 switch (params_format(params)) {
228 case SNDRV_PCM_FORMAT_S16_LE:
229 snd_soc_update_bits(codec,
230 TAS2770_TDMConfigurationReg2,
231 TAS2770_TDMConfigurationReg2_RXWLEN32_Mask,
232 TAS2770_TDMConfigurationReg2_RXWLEN32_16Bits);
233 pTAS2770->mnCh_size = 16;
234 if (pTAS2770->mnSlot_width == 0)
235 slot_width_tmp = 16;
236 break;
237 case SNDRV_PCM_FORMAT_S24_LE:
238 snd_soc_update_bits(codec,
239 TAS2770_TDMConfigurationReg2,
240 TAS2770_TDMConfigurationReg2_RXWLEN32_Mask,
241 TAS2770_TDMConfigurationReg2_RXWLEN32_24Bits);
242 pTAS2770->mnCh_size = 24;
243 if (pTAS2770->mnSlot_width == 0)
244 slot_width_tmp = 32;
245 break;
246 case SNDRV_PCM_FORMAT_S32_LE:
247 snd_soc_update_bits(codec,
248 TAS2770_TDMConfigurationReg2,
249 TAS2770_TDMConfigurationReg2_RXWLEN32_Mask,
250 TAS2770_TDMConfigurationReg2_RXWLEN32_32Bits);
251 pTAS2770->mnCh_size = 32;
252 if (pTAS2770->mnSlot_width == 0)
253 slot_width_tmp = 32;
254 break;
256 default:
257 dev_dbg(pTAS2770->dev, "Not supported params format\n");
258 return -EINVAL;
259 }
261 /* If machine driver did not call set slot width */
262 if (pTAS2770->mnSlot_width == 0)
263 tas2770_set_slot(codec, slot_width_tmp);
265 dev_dbg(pTAS2770->dev, "mnCh_size: %d\n", pTAS2770->mnCh_size);
266 snd_soc_update_bits(codec,
267 TAS2770_TDMConfigurationReg5,
268 TAS2770_TDMConfigurationReg5_VSNSTX_Mask |
269 TAS2770_TDMConfigurationReg5_VSNSSLOT50_Mask,
270 TAS2770_TDMConfigurationReg5_VSNSTX_Enable |
271 pTAS2770->mnVmon_slot_no);
272 snd_soc_update_bits(codec,
273 TAS2770_TDMConfigurationReg6,
274 TAS2770_TDMConfigurationReg6_ISNSTX_Mask |
275 TAS2770_TDMConfigurationReg6_ISNSSLOT50_Mask,
276 TAS2770_TDMConfigurationReg6_ISNSTX_Enable |
277 pTAS2770->mnImon_slot_no);
279 dev_dbg(pTAS2770->dev, "%s, sample rate: %d\n", __func__,
280 params_rate(params));
281 switch (params_rate(params)) {
282 case 48000:
283 snd_soc_update_bits(codec,
284 TAS2770_TDMConfigurationReg0,
285 TAS2770_TDMConfigurationReg0_SAMPRATERAMP_Mask,
286 TAS2770_TDMConfigurationReg0_SAMPRATERAMP_48KHz);
287 snd_soc_update_bits(codec,
288 TAS2770_TDMConfigurationReg0,
289 TAS2770_TDMConfigurationReg0_SAMPRATE31_Mask,
290 TAS2770_TDMConfigurationReg0_SAMPRATE31_44_1_48kHz);
291 break;
292 case 44100:
293 snd_soc_update_bits(codec,
294 TAS2770_TDMConfigurationReg0,
295 TAS2770_TDMConfigurationReg0_SAMPRATERAMP_Mask,
296 TAS2770_TDMConfigurationReg0_SAMPRATERAMP_44_1KHz);
297 snd_soc_update_bits(codec,
298 TAS2770_TDMConfigurationReg0,
299 TAS2770_TDMConfigurationReg0_SAMPRATE31_Mask,
300 TAS2770_TDMConfigurationReg0_SAMPRATE31_44_1_48kHz);
301 break;
302 case 96000:
303 snd_soc_update_bits(codec,
304 TAS2770_TDMConfigurationReg0,
305 TAS2770_TDMConfigurationReg0_SAMPRATERAMP_Mask,
306 TAS2770_TDMConfigurationReg0_SAMPRATERAMP_48KHz);
307 snd_soc_update_bits(codec,
308 TAS2770_TDMConfigurationReg0,
309 TAS2770_TDMConfigurationReg0_SAMPRATE31_Mask,
310 TAS2770_TDMConfigurationReg0_SAMPRATE31_88_2_96kHz);
311 break;
312 case 19200:
313 snd_soc_update_bits(codec,
314 TAS2770_TDMConfigurationReg0,
315 TAS2770_TDMConfigurationReg0_SAMPRATERAMP_Mask,
316 TAS2770_TDMConfigurationReg0_SAMPRATERAMP_48KHz);
317 snd_soc_update_bits(codec,
318 TAS2770_TDMConfigurationReg0,
319 TAS2770_TDMConfigurationReg0_SAMPRATE31_Mask,
320 TAS2770_TDMConfigurationReg0_SAMPRATE31_176_4_192kHz);
321 break;
322 default:
323 dev_dbg(pTAS2770->dev, "%s, unsupported sample rate\n", __func__);
325 }
326 return ret;
327 }
329 static int tas2770_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
330 {
331 u8 tdm_rx_start_slot = 0, asi_cfg_1 = 0;
332 struct snd_soc_codec *codec = dai->codec;
333 struct tas2770_priv *pTAS2770 = snd_soc_codec_get_drvdata(codec);
334 int ret = 0;
335 int value = 0;
337 dev_dbg(pTAS2770->dev, "%s, format=0x%x\n", __func__, fmt);
339 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
340 case SND_SOC_DAIFMT_CBS_CFS:
341 asi_cfg_1 = 0x00;
342 break;
343 default:
344 dev_err(pTAS2770->dev, "ASI format master is not found\n");
345 ret = -EINVAL;
346 }
348 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
349 case SND_SOC_DAIFMT_NB_NF:
350 dev_dbg(pTAS2770->dev, "INV format: NBNF\n");
351 asi_cfg_1 |= TAS2770_TDMConfigurationReg1_RXEDGE_Rising;
352 break;
353 case SND_SOC_DAIFMT_IB_NF:
354 dev_dbg(pTAS2770->dev, "INV format: IBNF\n");
355 asi_cfg_1 |= TAS2770_TDMConfigurationReg1_RXEDGE_Falling;
356 break;
357 default:
358 dev_err(pTAS2770->dev, "ASI format Inverse is not found\n");
359 ret = -EINVAL;
360 }
362 snd_soc_update_bits(codec, TAS2770_TDMConfigurationReg1,
363 TAS2770_TDMConfigurationReg1_RXEDGE_Mask,
364 asi_cfg_1);
366 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
367 case (SND_SOC_DAIFMT_I2S):
368 tdm_rx_start_slot = 1;
369 break;
370 case (SND_SOC_DAIFMT_DSP_A):
371 case (SND_SOC_DAIFMT_DSP_B):
372 tdm_rx_start_slot = 1;
373 break;
374 case (SND_SOC_DAIFMT_LEFT_J):
375 tdm_rx_start_slot = 0;
376 break;
377 default:
378 dev_err(pTAS2770->dev, "DAI Format is not found, fmt=0x%x\n", fmt);
379 ret = -EINVAL;
380 break;
381 }
383 snd_soc_update_bits(codec, TAS2770_TDMConfigurationReg1,
384 TAS2770_TDMConfigurationReg1_RXOFFSET51_Mask,
385 (tdm_rx_start_slot << TAS2770_TDMConfigurationReg1_RXOFFSET51_Shift));
387 snd_soc_update_bits(codec, TAS2770_TDMConfigurationReg3,
388 TAS2770_TDMConfigurationReg3_RXSLOTLeft30_Mask,
389 (pTAS2770->mnLeftSlot << TAS2770_TDMConfigurationReg3_RXSLOTLeft30_Shift));
390 snd_soc_update_bits(codec, TAS2770_TDMConfigurationReg3,
391 TAS2770_TDMConfigurationReg3_RXSLOTRight74_Mask,
392 (pTAS2770->mnRightSlot << TAS2770_TDMConfigurationReg3_RXSLOTRight74_Shift));
394 value = snd_soc_read(codec, TAS2770_TDMConfigurationReg3);
395 dev_dbg(pTAS2770->dev, "slot value: 0x%x", value);
397 return ret;
398 }
400 static int tas2770_set_slot(struct snd_soc_codec *codec, int slot_width)
401 {
402 int ret = 0;
403 struct tas2770_priv *pTAS2770 = snd_soc_codec_get_drvdata(codec);
405 switch (slot_width) {
406 case 16:
407 ret = snd_soc_update_bits(codec,
408 TAS2770_TDMConfigurationReg2,
409 TAS2770_TDMConfigurationReg2_RXSLEN10_Mask,
410 TAS2770_TDMConfigurationReg2_RXSLEN10_16Bits);
411 break;
413 case 24:
414 ret = snd_soc_update_bits(codec,
415 TAS2770_TDMConfigurationReg2,
416 TAS2770_TDMConfigurationReg2_RXSLEN10_Mask,
417 TAS2770_TDMConfigurationReg2_RXSLEN10_24Bits);
418 break;
420 case 32:
421 ret = snd_soc_update_bits(codec,
422 TAS2770_TDMConfigurationReg2,
423 TAS2770_TDMConfigurationReg2_RXSLEN10_Mask,
424 TAS2770_TDMConfigurationReg2_RXSLEN10_32Bits);
425 break;
427 case 0:
428 /* Do not change slot width */
429 break;
431 default:
432 dev_dbg(pTAS2770->dev, "slot width not supported");
433 ret = -EINVAL;
434 }
436 if (ret >= 0)
437 pTAS2770->mnSlot_width = slot_width;
439 return ret;
440 }
442 static int tas2770_set_dai_tdm_slot(struct snd_soc_dai *dai,
443 unsigned int tx_mask, unsigned int rx_mask,
444 int slots, int slot_width)
445 {
446 int ret = 0;
447 struct snd_soc_codec *codec = dai->codec;
448 struct tas2770_priv *pTAS2770 = snd_soc_codec_get_drvdata(codec);
450 dev_dbg(pTAS2770->dev, "%s, tx_mask:%d, rx_mask:%d, slots:%d, slot_width:%d",
451 __func__, tx_mask, rx_mask, slots, slot_width);
453 ret = tas2770_set_slot(codec, slot_width);
455 return ret;
456 }
458 static struct snd_soc_dai_ops tas2770_dai_ops = {
459 .digital_mute = tas2770_mute,
460 .hw_params = tas2770_hw_params,
461 .set_fmt = tas2770_set_dai_fmt,
462 .set_tdm_slot = tas2770_set_dai_tdm_slot,
463 };
465 #define TAS2770_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
466 SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
468 #define TAS2770_RATES (SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |\
469 SNDRV_PCM_RATE_96000 |\
470 SNDRV_PCM_RATE_192000\
471 )
473 static struct snd_soc_dai_driver tas2770_dai_driver[] = {
474 {
475 .name = "tas2770 ASI1",
476 .id = 0,
477 .playback = {
478 .stream_name = "ASI1 Playback",
479 .channels_min = 2,
480 .channels_max = 2,
481 .rates = TAS2770_RATES,
482 .formats = TAS2770_FORMATS,
483 },
484 .capture = {
485 .stream_name = "ASI1 Capture",
486 .channels_min = 0,
487 .channels_max = 2,
488 .rates = TAS2770_RATES,
489 .formats = TAS2770_FORMATS,
490 },
491 .ops = &tas2770_dai_ops,
492 .symmetric_rates = 1,
493 },
494 };
496 static int tas2770_codec_probe(struct snd_soc_codec *codec)
497 {
498 struct tas2770_priv *pTAS2770 = snd_soc_codec_get_drvdata(codec);
500 dev_err(pTAS2770->dev, "%s\n", __func__);
501 snd_soc_codec_init_regmap(codec, pTAS2770->regmap);
503 return 0;
504 }
506 static int tas2770_codec_remove(struct snd_soc_codec *codec)
507 {
508 return 0;
509 }
511 static DECLARE_TLV_DB_SCALE(tas2770_digital_tlv, 1100, 50, 0);
512 static DECLARE_TLV_DB_SCALE(tas2770_playback_volume, -10000, 50, 0);
514 static const struct snd_kcontrol_new tas2770_snd_controls[] = {
515 SOC_SINGLE_TLV("Amp Output Level", TAS2770_PlaybackConfigurationReg0,
516 0, TAS2770_PlaybackConfigurationReg0_AmplifierLevel40_Mask, 0,
517 tas2770_digital_tlv),
518 SOC_SINGLE_TLV("Playback Volume", TAS2770_PlaybackConfigurationReg2,
519 0, TAS2770_PlaybackConfigurationReg2_DVCPCM70_Mask, 1,
520 tas2770_playback_volume),
521 };
523 static struct snd_soc_codec_driver soc_codec_driver_tas2770 = {
524 .probe = tas2770_codec_probe,
525 .remove = tas2770_codec_remove,
526 .read = tas2770_codec_read,
527 .write = tas2770_codec_write,
528 .suspend = tas2770_codec_suspend,
529 .resume = tas2770_codec_resume,
530 .component_driver = {
531 .controls = tas2770_snd_controls,
532 .num_controls = ARRAY_SIZE(tas2770_snd_controls),
533 .dapm_widgets = tas2770_dapm_widgets,
534 .num_dapm_widgets = ARRAY_SIZE(tas2770_dapm_widgets),
535 .dapm_routes = tas2770_audio_map,
536 .num_dapm_routes = ARRAY_SIZE(tas2770_audio_map),
537 },
538 };
540 int tas2770_register_codec(struct tas2770_priv *pTAS2770)
541 {
542 int nResult = 0;
544 dev_info(pTAS2770->dev, "%s, enter\n", __func__);
545 nResult = snd_soc_register_codec(pTAS2770->dev,
546 &soc_codec_driver_tas2770,
547 tas2770_dai_driver, ARRAY_SIZE(tas2770_dai_driver));
549 return nResult;
550 }
552 int tas2770_deregister_codec(struct tas2770_priv *pTAS2770)
553 {
554 snd_soc_unregister_codec(pTAS2770->dev);
556 return 0;
557 }
559 MODULE_AUTHOR("Texas Instruments Inc.");
560 MODULE_DESCRIPTION("TAS2770 ALSA SOC Smart Amplifier driver");
561 MODULE_LICENSE("GPL v2");
562 #endif /* CONFIG_TAS2770_CODEC */