e47a024ef50660fad8b762f51813d625aaf6fcec
[tas2770sw-android/tas2770sw-android.git] / tas2770-codec.c
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 unsigned int tas2770_codec_read(struct snd_soc_codec *codec,
51                 unsigned int reg)
52 {
53         struct tas2770_priv *pTAS2770 = snd_soc_codec_get_drvdata(codec);
54         int nResult = 0;
55         unsigned int value = 0;
57         mutex_lock(&pTAS2770->dev_lock);
59         nResult = regmap_read(pTAS2770->regmap, reg, &value);
61         if (nResult < 0)
62                 dev_err(pTAS2770->dev, "%s, ERROR, reg=0x%x, E=%d\n",
63                         __func__, reg, nResult);
64         else
65                 dev_dbg(pTAS2770->dev, "%s, reg: 0x%x, value: 0x%x\n",
66                                 __func__, reg, value);
68         mutex_unlock(&pTAS2770->dev_lock);
70         if (nResult >= 0)
71                 return value;
72         else
73                 return nResult;
74 }
77 static int tas2770_codec_write(struct snd_soc_codec *codec, unsigned int reg,
78         unsigned int value)
79 {
80         struct tas2770_priv *pTAS2770 = snd_soc_codec_get_drvdata(codec);
82         int nResult = 0;
84         mutex_lock(&pTAS2770->dev_lock);
86         nResult = regmap_write(pTAS2770->regmap, reg, value);
87         if (nResult < 0)
88                 dev_err(pTAS2770->dev, "%s, ERROR, reg=0x%x, E=%d\n",
89                         __func__, reg, nResult);
90         else
91                 dev_dbg(pTAS2770->dev, "%s, reg: 0x%x, 0x%x\n",
92                         __func__, reg, value);
94         mutex_unlock(&pTAS2770->dev_lock);
96         return nResult;
98 }
101 static int tas2770_codec_suspend(struct snd_soc_codec *codec)
103         struct tas2770_priv *pTAS2770 = snd_soc_codec_get_drvdata(codec);
104         int ret = 0;
106         mutex_lock(&pTAS2770->codec_lock);
108         dev_dbg(pTAS2770->dev, "%s\n", __func__);
109         snd_soc_update_bits(codec, TAS2770_PowerControl,
110                         TAS2770_PowerControl_OperationalMode10_Mask,
111                         TAS2770_PowerControl_OperationalMode10_Shutdown);
112         mutex_unlock(&pTAS2770->codec_lock);
113         return ret;
116 static int tas2770_codec_resume(struct snd_soc_codec *codec)
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__);
124         snd_soc_update_bits(codec, TAS2770_PowerControl,
125                 TAS2770_PowerControl_OperationalMode10_Mask,
126                 TAS2770_PowerControl_OperationalMode10_Active);
128         mutex_unlock(&pTAS2770->codec_lock);
129         return ret;
132 static const char * const tas2770_ASI1_src[] = {
133         "I2C offset", "Left", "Right", "LeftRightDiv2",
134 };
136 static SOC_ENUM_SINGLE_DECL(
137         tas2770_ASI1_src_enum, TAS2770_TDMConfigurationReg2,
138         4, tas2770_ASI1_src);
140 static const struct snd_kcontrol_new tas2770_asi1_mux =
141         SOC_DAPM_ENUM("ASI1 Source", tas2770_ASI1_src_enum);
144 static int tas2770_dac_event(struct snd_soc_dapm_widget *w,
145                         struct snd_kcontrol *kcontrol, int event)
147         struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
149         switch (event) {
150         case SND_SOC_DAPM_POST_PMU:
151                 snd_soc_update_bits(codec, TAS2770_PowerControl,
152                         TAS2770_PowerControl_OperationalMode10_Mask,
153                         TAS2770_PowerControl_OperationalMode10_Active);
154                 break;
155         case SND_SOC_DAPM_PRE_PMD:
156                 snd_soc_update_bits(codec, TAS2770_PowerControl,
157                         TAS2770_PowerControl_OperationalMode10_Mask,
158                         TAS2770_PowerControl_OperationalMode10_Shutdown);
159                 break;
161         }
162         return 0;
166 static const struct snd_kcontrol_new isense_switch =
167         SOC_DAPM_SINGLE("Switch", TAS2770_PowerControl, 3, 1, 1);
168 static const struct snd_kcontrol_new vsense_switch =
169         SOC_DAPM_SINGLE("Switch", TAS2770_PowerControl, 2, 1, 1);
171 static const struct snd_soc_dapm_widget tas2770_dapm_widgets[] = {
172         SND_SOC_DAPM_AIF_IN("ASI1", "ASI1 Playback", 0, SND_SOC_NOPM, 0, 0),
173         SND_SOC_DAPM_MUX("ASI1 Sel", SND_SOC_NOPM, 0, 0,
174                                 &tas2770_asi1_mux),
175         SND_SOC_DAPM_SWITCH("ISENSE", TAS2770_PowerControl, 3, 1,
176                         &isense_switch),
177         SND_SOC_DAPM_SWITCH("VSENSE", TAS2770_PowerControl, 2, 1,
178                         &vsense_switch),
179         SND_SOC_DAPM_DAC_E("DAC", NULL, SND_SOC_NOPM, 0, 0, tas2770_dac_event,
180         SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
181         SND_SOC_DAPM_OUTPUT("OUT"),
182         SND_SOC_DAPM_SIGGEN("VMON"),
183         SND_SOC_DAPM_SIGGEN("IMON")
184 };
186 static const struct snd_soc_dapm_route tas2770_audio_map[] = {
187         {"ASI1 Sel", "I2C offset", "ASI1"},
188         {"ASI1 Sel", "Left", "ASI1"},
189         {"ASI1 Sel", "Right", "ASI1"},
190         {"ASI1 Sel", "LeftRightDiv2", "ASI1"},
191         {"DAC", NULL, "ASI1 Sel"},
192         {"OUT", NULL, "DAC"},
193         {"ISENSE", "Switch", "IMON"},
194         {"VSENSE", "Switch", "VMON"},
195 };
198 static int tas2770_mute(struct snd_soc_dai *dai, int mute)
200         struct snd_soc_codec *codec = dai->codec;
201         struct tas2770_priv *pTAS2770 = snd_soc_codec_get_drvdata(codec);
202         dev_dbg(pTAS2770->dev, "%s\n", __func__);
204         mutex_lock(&pTAS2770->codec_lock);
205         if (mute) {
206                 snd_soc_update_bits(codec, TAS2770_PowerControl,
207                         TAS2770_PowerControl_OperationalMode10_Mask,
208                         TAS2770_PowerControl_OperationalMode10_Mute);
209         } else {
210                 snd_soc_update_bits(codec, TAS2770_PowerControl,
211                         TAS2770_PowerControl_OperationalMode10_Mask,
212                         TAS2770_PowerControl_OperationalMode10_Active);
213         }
214         mutex_unlock(&pTAS2770->codec_lock);
215         return 0;
218 static int tas2770_hw_params(struct snd_pcm_substream *substream,
219                 struct snd_pcm_hw_params *params,
220                 struct snd_soc_dai *dai)
222         struct snd_soc_codec *codec = dai->codec;
223         struct tas2770_priv *pTAS2770 = snd_soc_codec_get_drvdata(codec);
224         int ret = 0;
226         dev_dbg(pTAS2770->dev, "%s, format: %d\n", __func__,
227                 params_format(params));
229         switch (params_format(params)) {
230         case SNDRV_PCM_FORMAT_S16_LE:
231                 snd_soc_update_bits(codec,
232                         TAS2770_TDMConfigurationReg2,
233                         TAS2770_TDMConfigurationReg2_RXWLEN32_Mask |
234                         TAS2770_TDMConfigurationReg2_RXSLEN10_Mask,
235                         TAS2770_TDMConfigurationReg2_RXWLEN32_16Bits |
236                         TAS2770_TDMConfigurationReg2_RXSLEN10_16Bits);
237                         pTAS2770->ch_size = 16;
238                 break;
239         case SNDRV_PCM_FORMAT_S24_LE:
240                         snd_soc_update_bits(codec,
241                         TAS2770_TDMConfigurationReg2,
242                         TAS2770_TDMConfigurationReg2_RXWLEN32_Mask |
243                         TAS2770_TDMConfigurationReg2_RXSLEN10_Mask,
244                         TAS2770_TDMConfigurationReg2_RXWLEN32_24Bits  |
245                         TAS2770_TDMConfigurationReg2_RXSLEN10_32Bits);
246                         pTAS2770->ch_size = 32;
247                 break;
248         case SNDRV_PCM_FORMAT_S32_LE:
249                         snd_soc_update_bits(codec,
250                         TAS2770_TDMConfigurationReg2,
251                         TAS2770_TDMConfigurationReg2_RXWLEN32_Mask |
252                         TAS2770_TDMConfigurationReg2_RXSLEN10_Mask,
253                         TAS2770_TDMConfigurationReg2_RXWLEN32_32Bits |
254                         TAS2770_TDMConfigurationReg2_RXSLEN10_32Bits);
255                         pTAS2770->ch_size = 32;
256                 break;
258         }
260         dev_dbg(pTAS2770->dev, "ch_size: %d\n", pTAS2770->ch_size);
261         snd_soc_update_bits(codec,
262                 TAS2770_TDMConfigurationReg5,
263                 TAS2770_TDMConfigurationReg5_VSNSTX_Mask |
264                 TAS2770_TDMConfigurationReg5_VSNSSLOT50_Mask,
265                 TAS2770_TDMConfigurationReg5_VSNSTX_Enable |
266                 (pTAS2770->ch_size >> 3));
267         snd_soc_update_bits(codec,
268                 TAS2770_TDMConfigurationReg6,
269                 TAS2770_TDMConfigurationReg6_ISNSTX_Mask |
270                 TAS2770_TDMConfigurationReg6_ISNSSLOT50_Mask,
271                 TAS2770_TDMConfigurationReg6_ISNSTX_Enable);
273         dev_dbg(pTAS2770->dev, "%s, sample rate: %d\n", __func__,
274                 params_rate(params));
275         switch (params_rate(params)) {
276         case 48000:
277                         snd_soc_update_bits(codec,
278                                 TAS2770_TDMConfigurationReg0,
279                                 TAS2770_TDMConfigurationReg0_SAMPRATERAMP_Mask,
280                                 TAS2770_TDMConfigurationReg0_SAMPRATERAMP_48KHz);
281                         snd_soc_update_bits(codec,
282                                 TAS2770_TDMConfigurationReg0,
283                                 TAS2770_TDMConfigurationReg0_SAMPRATE31_Mask,
284                                 TAS2770_TDMConfigurationReg0_SAMPRATE31_44_1_48kHz);
285                         break;
286         case 44100:
287                         snd_soc_update_bits(codec,
288                                 TAS2770_TDMConfigurationReg0,
289                                 TAS2770_TDMConfigurationReg0_SAMPRATERAMP_Mask,
290                                 TAS2770_TDMConfigurationReg0_SAMPRATERAMP_44_1KHz);
291                         snd_soc_update_bits(codec,
292                                 TAS2770_TDMConfigurationReg0,
293                                 TAS2770_TDMConfigurationReg0_SAMPRATE31_Mask,
294                                 TAS2770_TDMConfigurationReg0_SAMPRATE31_44_1_48kHz);
295                         break;
296         case 96000:
297                         snd_soc_update_bits(codec,
298                                 TAS2770_TDMConfigurationReg0,
299                                 TAS2770_TDMConfigurationReg0_SAMPRATERAMP_Mask,
300                                 TAS2770_TDMConfigurationReg0_SAMPRATERAMP_48KHz);
301                         snd_soc_update_bits(codec,
302                                 TAS2770_TDMConfigurationReg0,
303                                 TAS2770_TDMConfigurationReg0_SAMPRATE31_Mask,
304                                 TAS2770_TDMConfigurationReg0_SAMPRATE31_88_2_96kHz);
305                         break;
306         case 19200:
307                         snd_soc_update_bits(codec,
308                                 TAS2770_TDMConfigurationReg0,
309                                 TAS2770_TDMConfigurationReg0_SAMPRATERAMP_Mask,
310                                 TAS2770_TDMConfigurationReg0_SAMPRATERAMP_48KHz);
311                         snd_soc_update_bits(codec,
312                                 TAS2770_TDMConfigurationReg0,
313                                 TAS2770_TDMConfigurationReg0_SAMPRATE31_Mask,
314                                 TAS2770_TDMConfigurationReg0_SAMPRATE31_176_4_192kHz);
315                         break;
316         default:
317                         dev_dbg(pTAS2770->dev, "%s, unsupported sample rate\n", __func__);
319         }
320         return ret;
323 static int tas2770_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
325         u8 tdm_rx_start_slot = 0, asi_cfg_1 = 0;
326         struct snd_soc_codec *codec = dai->codec;
327         struct tas2770_priv *pTAS2770 = snd_soc_codec_get_drvdata(codec);
328         int ret = 0;
329         int value = 0;
331         dev_dbg(pTAS2770->dev, "%s, format=0x%x\n", __func__, fmt);
333         switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
334         case SND_SOC_DAIFMT_CBS_CFS:
335                 asi_cfg_1 = 0x00;
336                 break;
337         default:
338                 dev_err(pTAS2770->dev, "ASI format master is not found\n");
339                 ret = -EINVAL;
340         }
342         switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
343         case SND_SOC_DAIFMT_NB_NF:
344                 dev_dbg(pTAS2770->dev, "INV format: NBNF\n");
345                 asi_cfg_1 |= TAS2770_TDMConfigurationReg1_RXEDGE_Rising;
346                 break;
347         case SND_SOC_DAIFMT_IB_NF:
348                 dev_dbg(pTAS2770->dev, "INV format: IBNF\n");
349                 asi_cfg_1 |= TAS2770_TDMConfigurationReg1_RXEDGE_Falling;
350                 break;
351         default:
352                 dev_err(pTAS2770->dev, "ASI format Inverse is not found\n");
353                 ret = -EINVAL;
354         }
356         snd_soc_update_bits(codec, TAS2770_TDMConfigurationReg1,
357                 TAS2770_TDMConfigurationReg1_RXEDGE_Mask,
358                 asi_cfg_1);
360         switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
361         case (SND_SOC_DAIFMT_I2S):
362                 tdm_rx_start_slot = 1;
363                 break;
364         case (SND_SOC_DAIFMT_DSP_A):
365         case (SND_SOC_DAIFMT_DSP_B):
366                 tdm_rx_start_slot = 1;
367                 break;
368         case (SND_SOC_DAIFMT_LEFT_J):
369                 tdm_rx_start_slot = 0;
370                 break;
371         default:
372         dev_err(pTAS2770->dev, "DAI Format is not found, fmt=0x%x\n", fmt);
373         ret = -EINVAL;
374                 break;
375         }
377         snd_soc_update_bits(codec, TAS2770_TDMConfigurationReg1,
378                 TAS2770_TDMConfigurationReg1_RXOFFSET51_Mask,
379         (tdm_rx_start_slot << TAS2770_TDMConfigurationReg1_RXOFFSET51_Shift));
381         snd_soc_update_bits(codec, TAS2770_TDMConfigurationReg3,
382                 TAS2770_TDMConfigurationReg3_RXSLOTLeft30_Mask,
383                 (pTAS2770->mnLeftSlot << TAS2770_TDMConfigurationReg3_RXSLOTLeft30_Shift));
384         snd_soc_update_bits(codec, TAS2770_TDMConfigurationReg3,
385                 TAS2770_TDMConfigurationReg3_RXSLOTRight74_Mask,
386         (pTAS2770->mnRightSlot << TAS2770_TDMConfigurationReg3_RXSLOTRight74_Shift));
388         value = snd_soc_read(codec, TAS2770_TDMConfigurationReg3);
389         dev_dbg(pTAS2770->dev, "slot value: 0x%x", value);
391         return ret;
394 static struct snd_soc_dai_ops tas2770_dai_ops = {
395         .digital_mute = tas2770_mute,
396         .hw_params  = tas2770_hw_params,
397         .set_fmt    = tas2770_set_dai_fmt,
398 };
400 #define TAS2770_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
401                 SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
403 #define TAS2770_RATES (SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |\
404                                                 SNDRV_PCM_RATE_96000 |\
405                                                 SNDRV_PCM_RATE_192000\
406                                                 )
408 static struct snd_soc_dai_driver tas2770_dai_driver[] = {
409         {
410                 .name = "tas2770 ASI1",
411                 .id = 0,
412                 .playback = {
413                         .stream_name    = "ASI1 Playback",
414                         .channels_min   = 2,
415                         .channels_max   = 2,
416                         .rates      = TAS2770_RATES,
417                         .formats    = TAS2770_FORMATS,
418                 },
419                 .capture = {
420                         .stream_name    = "ASI1 Capture",
421                         .channels_min   = 0,
422                         .channels_max   = 2,
423                         .rates          = TAS2770_RATES,
424                         .formats    = TAS2770_FORMATS,
425                 },
426                 .ops = &tas2770_dai_ops,
427                 .symmetric_rates = 1,
428         },
429 };
431 static int tas2770_codec_probe(struct snd_soc_codec *codec)
433         struct tas2770_priv *pTAS2770 = snd_soc_codec_get_drvdata(codec);
435         dev_err(pTAS2770->dev, "%s\n", __func__);
437         return 0;
440 static int tas2770_codec_remove(struct snd_soc_codec *codec)
442         return 0;
445 static DECLARE_TLV_DB_SCALE(tas2770_digital_tlv, 1100, 50, 0);
447 static const struct snd_kcontrol_new tas2770_snd_controls[] = {
448         SOC_SINGLE_TLV("Amp Output Level", TAS2770_PlaybackConfigurationReg0,
449                 0, TAS2770_PlaybackConfigurationReg0_AmplifierLevel40_Mask, 0,
450                 tas2770_digital_tlv),
451 };
453 static struct snd_soc_codec_driver soc_codec_driver_tas2770 = {
454         .probe                  = tas2770_codec_probe,
455         .remove                 = tas2770_codec_remove,
456         .read                   = tas2770_codec_read,
457         .write                  = tas2770_codec_write,
458         .suspend                = tas2770_codec_suspend,
459         .resume                 = tas2770_codec_resume,
460         .component_driver = {
461                 .controls               = tas2770_snd_controls,
462                 .num_controls           = ARRAY_SIZE(tas2770_snd_controls),
463                 .dapm_widgets           = tas2770_dapm_widgets,
464                 .num_dapm_widgets       = ARRAY_SIZE(tas2770_dapm_widgets),
465                 .dapm_routes            = tas2770_audio_map,
466                 .num_dapm_routes        = ARRAY_SIZE(tas2770_audio_map),
467         },
468 };
470 int tas2770_register_codec(struct tas2770_priv *pTAS2770)
472         int nResult = 0;
474         dev_info(pTAS2770->dev, "%s, enter\n", __func__);
475         nResult = snd_soc_register_codec(pTAS2770->dev,
476                 &soc_codec_driver_tas2770,
477                 tas2770_dai_driver, ARRAY_SIZE(tas2770_dai_driver));
479         return nResult;
482 int tas2770_deregister_codec(struct tas2770_priv *pTAS2770)
484         snd_soc_unregister_codec(pTAS2770->dev);
486         return 0;
489 MODULE_AUTHOR("Texas Instruments Inc.");
490 MODULE_DESCRIPTION("TAS2770 ALSA SOC Smart Amplifier driver");
491 MODULE_LICENSE("GPL v2");
492 #endif /* CONFIG_TAS2770_CODEC */