1e4e852969d68c5ef37128e5396c0a8574de207f
[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 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;
103 static int tas2770_codec_suspend(struct snd_soc_codec *codec)
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;
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__);
125         mutex_unlock(&pTAS2770->codec_lock);
126         return ret;
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);
140 static int tas2770_set_power_state(struct tas2770_priv *pTAS2770, int state)
142         struct snd_soc_codec *codec = pTAS2770->codec;
144         switch (state) {
145         case TAS2770_POWER_ACTIVE:
146                 snd_soc_update_bits(codec, TAS2770_PowerControl,
147                         TAS2770_PowerControl_OperationalMode10_Mask,
148                         TAS2770_PowerControl_OperationalMode10_Active);
149                 break;
151         case TAS2770_POWER_MUTE:
152                 snd_soc_update_bits(codec, TAS2770_PowerControl,
153                         TAS2770_PowerControl_OperationalMode10_Mask,
154                         TAS2770_PowerControl_OperationalMode10_Mute);
155                 break;
157         case TAS2770_POWER_SHUTDOWN:
158                 snd_soc_update_bits(codec, TAS2770_PowerControl,
159                         TAS2770_PowerControl_OperationalMode10_Mask,
160                         TAS2770_PowerControl_OperationalMode10_Shutdown);
161                 break;
163         default:
164                 dev_err(pTAS2770->dev, "wrong power state setting %d\n", state);
166         }
168         pTAS2770->mnPowerState = state;
169         return 0;
172 static int tas2770_dac_event(struct snd_soc_dapm_widget *w,
173                         struct snd_kcontrol *kcontrol, int event)
175         struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
176         struct tas2770_priv *pTAS2770 = snd_soc_codec_get_drvdata(codec);
178         mutex_lock(&pTAS2770->codec_lock);
180         switch (event) {
181         case SND_SOC_DAPM_POST_PMU:
182                 tas2770_set_power_state(pTAS2770, TAS2770_POWER_MUTE);
183                 break;
184         case SND_SOC_DAPM_PRE_PMD:
185                 tas2770_set_power_state(pTAS2770, TAS2770_POWER_SHUTDOWN);
186                 break;
188         }
190         mutex_unlock(&pTAS2770->codec_lock);
191         return 0;
194 static const struct snd_kcontrol_new isense_switch =
195         SOC_DAPM_SINGLE("Switch", TAS2770_PowerControl, 3, 1, 1);
196 static const struct snd_kcontrol_new vsense_switch =
197         SOC_DAPM_SINGLE("Switch", TAS2770_PowerControl, 2, 1, 1);
199 static const struct snd_soc_dapm_widget tas2770_dapm_widgets[] = {
200         SND_SOC_DAPM_AIF_IN("ASI1", "ASI1 Playback", 0, SND_SOC_NOPM, 0, 0),
201         SND_SOC_DAPM_MUX("ASI1 Sel", SND_SOC_NOPM, 0, 0,
202                                 &tas2770_asi1_mux),
203         SND_SOC_DAPM_SWITCH("ISENSE", TAS2770_PowerControl, 3, 1,
204                         &isense_switch),
205         SND_SOC_DAPM_SWITCH("VSENSE", TAS2770_PowerControl, 2, 1,
206                         &vsense_switch),
207         SND_SOC_DAPM_DAC_E("DAC", NULL, SND_SOC_NOPM, 0, 0, tas2770_dac_event,
208         SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
209         SND_SOC_DAPM_OUTPUT("OUT"),
210         SND_SOC_DAPM_SIGGEN("VMON"),
211         SND_SOC_DAPM_SIGGEN("IMON")
212 };
214 static const struct snd_soc_dapm_route tas2770_audio_map[] = {
215         {"ASI1 Sel", "I2C offset", "ASI1"},
216         {"ASI1 Sel", "Left", "ASI1"},
217         {"ASI1 Sel", "Right", "ASI1"},
218         {"ASI1 Sel", "LeftRightDiv2", "ASI1"},
219         {"DAC", NULL, "ASI1 Sel"},
220         {"OUT", NULL, "DAC"},
221         {"ISENSE", "Switch", "IMON"},
222         {"VSENSE", "Switch", "VMON"},
223 };
226 static int tas2770_mute(struct snd_soc_dai *dai, int mute)
228         struct snd_soc_codec *codec = dai->codec;
229         struct tas2770_priv *pTAS2770 = snd_soc_codec_get_drvdata(codec);
230         dev_dbg(pTAS2770->dev, "%s\n", __func__);
232         mutex_lock(&pTAS2770->codec_lock);
233         if (mute) {
234                 tas2770_set_power_state(pTAS2770, TAS2770_POWER_MUTE);
235         } else {
236                 tas2770_set_power_state(pTAS2770, TAS2770_POWER_ACTIVE);
237         }
238         mutex_unlock(&pTAS2770->codec_lock);
239         return 0;
242 static int tas2770_set_bitwidth(struct tas2770_priv *pTAS2770, int bitwidth)
244         switch (bitwidth) {
245         case SNDRV_PCM_FORMAT_S16_LE:
246                 snd_soc_update_bits(pTAS2770->codec,
247                         TAS2770_TDMConfigurationReg2,
248                         TAS2770_TDMConfigurationReg2_RXWLEN32_Mask,
249                         TAS2770_TDMConfigurationReg2_RXWLEN32_16Bits);
250                         /* If machine driver did not call set slot width */
251                         if (pTAS2770->mnSlot_width == 0)
252                                 tas2770_set_slot(pTAS2770->codec, 16);
253                 pTAS2770->mnVmon_slot_no = pTAS2770->mnImon_slot_no + 2;
254                 break;
255         case SNDRV_PCM_FORMAT_S24_LE:
256                         snd_soc_update_bits(pTAS2770->codec,
257                         TAS2770_TDMConfigurationReg2,
258                         TAS2770_TDMConfigurationReg2_RXWLEN32_Mask,
259                         TAS2770_TDMConfigurationReg2_RXWLEN32_24Bits);
260                         if (pTAS2770->mnSlot_width == 0)
261                                 tas2770_set_slot(pTAS2770->codec, 32);
262                 pTAS2770->mnVmon_slot_no = pTAS2770->mnImon_slot_no + 4;
263                 break;
264         case SNDRV_PCM_FORMAT_S32_LE:
265                         snd_soc_update_bits(pTAS2770->codec,
266                         TAS2770_TDMConfigurationReg2,
267                         TAS2770_TDMConfigurationReg2_RXWLEN32_Mask,
268                         TAS2770_TDMConfigurationReg2_RXWLEN32_32Bits);
269                         if (pTAS2770->mnSlot_width == 0)
270                                 tas2770_set_slot(pTAS2770->codec, 32);
271                 pTAS2770->mnVmon_slot_no = pTAS2770->mnImon_slot_no + 4;
272                 break;
274         default:
275                 dev_dbg(pTAS2770->dev, "Not supported params format\n");
276                 return -EINVAL;
277         }
279         pTAS2770->mnCh_size = bitwidth;
280         dev_dbg(pTAS2770->dev, "mnCh_size: %d\n", pTAS2770->mnCh_size);
282         snd_soc_update_bits(pTAS2770->codec,
283                 TAS2770_TDMConfigurationReg5,
284                 TAS2770_TDMConfigurationReg5_VSNSTX_Mask |
285                 TAS2770_TDMConfigurationReg5_VSNSSLOT50_Mask,
286                 TAS2770_TDMConfigurationReg5_VSNSTX_Enable |
287                 pTAS2770->mnVmon_slot_no);
288         snd_soc_update_bits(pTAS2770->codec,
289                 TAS2770_TDMConfigurationReg6,
290                 TAS2770_TDMConfigurationReg6_ISNSTX_Mask |
291                 TAS2770_TDMConfigurationReg6_ISNSSLOT50_Mask,
292                 TAS2770_TDMConfigurationReg6_ISNSTX_Enable |
293                 pTAS2770->mnImon_slot_no);
295         return 0;
298 static int tas2770_set_samplerate(struct tas2770_priv *pTAS2770, int samplerate)
300         switch (samplerate) {
301         case 48000:
302                         snd_soc_update_bits(pTAS2770->codec,
303                                 TAS2770_TDMConfigurationReg0,
304                                 TAS2770_TDMConfigurationReg0_SAMPRATERAMP_Mask,
305                                 TAS2770_TDMConfigurationReg0_SAMPRATERAMP_48KHz);
306                         snd_soc_update_bits(pTAS2770->codec,
307                                 TAS2770_TDMConfigurationReg0,
308                                 TAS2770_TDMConfigurationReg0_SAMPRATE31_Mask,
309                                 TAS2770_TDMConfigurationReg0_SAMPRATE31_44_1_48kHz);
310                         break;
311         case 44100:
312                         snd_soc_update_bits(pTAS2770->codec,
313                                 TAS2770_TDMConfigurationReg0,
314                                 TAS2770_TDMConfigurationReg0_SAMPRATERAMP_Mask,
315                                 TAS2770_TDMConfigurationReg0_SAMPRATERAMP_44_1KHz);
316                         snd_soc_update_bits(pTAS2770->codec,
317                                 TAS2770_TDMConfigurationReg0,
318                                 TAS2770_TDMConfigurationReg0_SAMPRATE31_Mask,
319                                 TAS2770_TDMConfigurationReg0_SAMPRATE31_44_1_48kHz);
320                         break;
321         case 96000:
322                         snd_soc_update_bits(pTAS2770->codec,
323                                 TAS2770_TDMConfigurationReg0,
324                                 TAS2770_TDMConfigurationReg0_SAMPRATERAMP_Mask,
325                                 TAS2770_TDMConfigurationReg0_SAMPRATERAMP_48KHz);
326                         snd_soc_update_bits(pTAS2770->codec,
327                                 TAS2770_TDMConfigurationReg0,
328                                 TAS2770_TDMConfigurationReg0_SAMPRATE31_Mask,
329                                 TAS2770_TDMConfigurationReg0_SAMPRATE31_88_2_96kHz);
330                         break;
331         case 88200:
332                         snd_soc_update_bits(pTAS2770->codec,
333                                 TAS2770_TDMConfigurationReg0,
334                                 TAS2770_TDMConfigurationReg0_SAMPRATERAMP_Mask,
335                                 TAS2770_TDMConfigurationReg0_SAMPRATERAMP_44_1KHz);
336                         snd_soc_update_bits(pTAS2770->codec,
337                                 TAS2770_TDMConfigurationReg0,
338                                 TAS2770_TDMConfigurationReg0_SAMPRATE31_Mask,
339                                 TAS2770_TDMConfigurationReg0_SAMPRATE31_88_2_96kHz);
340                         break;
341         case 19200:
342                         snd_soc_update_bits(pTAS2770->codec,
343                                 TAS2770_TDMConfigurationReg0,
344                                 TAS2770_TDMConfigurationReg0_SAMPRATERAMP_Mask,
345                                 TAS2770_TDMConfigurationReg0_SAMPRATERAMP_48KHz);
346                         snd_soc_update_bits(pTAS2770->codec,
347                                 TAS2770_TDMConfigurationReg0,
348                                 TAS2770_TDMConfigurationReg0_SAMPRATE31_Mask,
349                                 TAS2770_TDMConfigurationReg0_SAMPRATE31_176_4_192kHz);
350                         break;
351         case 17640:
352                         snd_soc_update_bits(pTAS2770->codec,
353                                 TAS2770_TDMConfigurationReg0,
354                                 TAS2770_TDMConfigurationReg0_SAMPRATERAMP_Mask,
355                                 TAS2770_TDMConfigurationReg0_SAMPRATERAMP_44_1KHz);
356                         snd_soc_update_bits(pTAS2770->codec,
357                                 TAS2770_TDMConfigurationReg0,
358                                 TAS2770_TDMConfigurationReg0_SAMPRATE31_Mask,
359                                 TAS2770_TDMConfigurationReg0_SAMPRATE31_176_4_192kHz);
360                         break;
361         default:
362                         dev_dbg(pTAS2770->dev, "%s, unsupported sample rate\n", __func__);
364         }
366         pTAS2770->mnSamplingRate = samplerate;
367         return 0;
370 static int tas2770_hw_params(struct snd_pcm_substream *substream,
371                 struct snd_pcm_hw_params *params,
372                 struct snd_soc_dai *dai)
374         struct snd_soc_codec *codec = dai->codec;
375         struct tas2770_priv *pTAS2770 = snd_soc_codec_get_drvdata(codec);
376         int ret = 0;
378         dev_dbg(pTAS2770->dev, "%s, format: %d\n", __func__,
379                 params_format(params));
381         mutex_lock(&pTAS2770->codec_lock);
383         ret = tas2770_set_bitwidth(pTAS2770, params_format(params));
384         if(ret < 0)
385                 return ret;
387         dev_dbg(pTAS2770->dev, "%s, sample rate: %d\n", __func__,
388                 params_rate(params));
390         ret = tas2770_set_samplerate(pTAS2770, params_rate(params));
392         mutex_unlock(&pTAS2770->codec_lock);
393         return ret;
396 static int tas2770_set_fmt(struct tas2770_priv *pTAS2770, unsigned int fmt)
398         u8 tdm_rx_start_slot = 0, asi_cfg_1 = 0;
399         int ret = 0;
400         int value = 0;
402         switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
403         case SND_SOC_DAIFMT_CBS_CFS:
404                 asi_cfg_1 = 0x00;
405                 break;
406         default:
407                 dev_err(pTAS2770->dev, "ASI format master is not found\n");
408                 ret = -EINVAL;
409         }
411         switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
412         case SND_SOC_DAIFMT_NB_NF:
413                 dev_dbg(pTAS2770->dev, "INV format: NBNF\n");
414                 asi_cfg_1 |= TAS2770_TDMConfigurationReg1_RXEDGE_Rising;
415                 break;
416         case SND_SOC_DAIFMT_IB_NF:
417                 dev_dbg(pTAS2770->dev, "INV format: IBNF\n");
418                 asi_cfg_1 |= TAS2770_TDMConfigurationReg1_RXEDGE_Falling;
419                 break;
420         default:
421                 dev_err(pTAS2770->dev, "ASI format Inverse is not found\n");
422                 ret = -EINVAL;
423         }
425         snd_soc_update_bits(pTAS2770->codec, TAS2770_TDMConfigurationReg1,
426                 TAS2770_TDMConfigurationReg1_RXEDGE_Mask,
427                 asi_cfg_1);
429         switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
430         case (SND_SOC_DAIFMT_I2S):
431                 tdm_rx_start_slot = 1;
432                 break;
433         case (SND_SOC_DAIFMT_DSP_A):
434         case (SND_SOC_DAIFMT_DSP_B):
435                 tdm_rx_start_slot = 1;
436                 break;
437         case (SND_SOC_DAIFMT_LEFT_J):
438                 tdm_rx_start_slot = 0;
439                 break;
440         default:
441         dev_err(pTAS2770->dev, "DAI Format is not found, fmt=0x%x\n", fmt);
442         ret = -EINVAL;
443                 break;
444         }
446         snd_soc_update_bits(pTAS2770->codec, TAS2770_TDMConfigurationReg1,
447                 TAS2770_TDMConfigurationReg1_RXOFFSET51_Mask,
448         (tdm_rx_start_slot << TAS2770_TDMConfigurationReg1_RXOFFSET51_Shift));
450         snd_soc_update_bits(pTAS2770->codec, TAS2770_TDMConfigurationReg3,
451                 TAS2770_TDMConfigurationReg3_RXSLOTLeft30_Mask,
452                 (pTAS2770->mnLeftSlot << TAS2770_TDMConfigurationReg3_RXSLOTLeft30_Shift));
453         snd_soc_update_bits(pTAS2770->codec, TAS2770_TDMConfigurationReg3,
454                 TAS2770_TDMConfigurationReg3_RXSLOTRight74_Mask,
455         (pTAS2770->mnRightSlot << TAS2770_TDMConfigurationReg3_RXSLOTRight74_Shift));
457         value = snd_soc_read(pTAS2770->codec, TAS2770_TDMConfigurationReg3);
458         dev_dbg(pTAS2770->dev, "slot value: 0x%x", value);
460         pTAS2770->mnASIFormat = fmt;
462         return 0;
465 static int tas2770_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
467         struct snd_soc_codec *codec = dai->codec;
468         struct tas2770_priv *pTAS2770 = snd_soc_codec_get_drvdata(codec);
469         int ret = 0;
471         dev_dbg(pTAS2770->dev, "%s, format=0x%x\n", __func__, fmt);
472         mutex_lock(&pTAS2770->codec_lock);
474         ret = tas2770_set_fmt(pTAS2770, fmt);
476         mutex_unlock(&pTAS2770->codec_lock);
477         return ret;
480 static int tas2770_set_slot(struct snd_soc_codec *codec, int slot_width)
482         int ret = 0;
483         struct tas2770_priv *pTAS2770 = snd_soc_codec_get_drvdata(codec);
485         switch (slot_width) {
486         case 16:
487         ret = snd_soc_update_bits(codec,
488                 TAS2770_TDMConfigurationReg2,
489                 TAS2770_TDMConfigurationReg2_RXSLEN10_Mask,
490                 TAS2770_TDMConfigurationReg2_RXSLEN10_16Bits);
491         break;
493         case 24:
494         ret = snd_soc_update_bits(codec,
495                 TAS2770_TDMConfigurationReg2,
496                 TAS2770_TDMConfigurationReg2_RXSLEN10_Mask,
497                 TAS2770_TDMConfigurationReg2_RXSLEN10_24Bits);
498         break;
500         case 32:
501         ret = snd_soc_update_bits(codec,
502                 TAS2770_TDMConfigurationReg2,
503                 TAS2770_TDMConfigurationReg2_RXSLEN10_Mask,
504                 TAS2770_TDMConfigurationReg2_RXSLEN10_32Bits);
505         break;
507         case 0:
508         /* Do not change slot width */
509         break;
511         default:
512                 dev_dbg(pTAS2770->dev, "slot width not supported");
513                 ret = -EINVAL;
514         }
516         if (ret >= 0)
517                 pTAS2770->mnSlot_width = slot_width;
519         return ret;
522 static int tas2770_set_dai_tdm_slot(struct snd_soc_dai *dai,
523                 unsigned int tx_mask, unsigned int rx_mask,
524                 int slots, int slot_width)
526         int ret = 0;
527         struct snd_soc_codec *codec = dai->codec;
528         struct tas2770_priv *pTAS2770 = snd_soc_codec_get_drvdata(codec);
530         dev_dbg(pTAS2770->dev, "%s, tx_mask:%d, rx_mask:%d, slots:%d, slot_width:%d",
531                         __func__, tx_mask, rx_mask, slots, slot_width);
533         mutex_lock(&pTAS2770->codec_lock);
534         ret = tas2770_set_slot(codec, slot_width);
535         mutex_unlock(&pTAS2770->codec_lock);
537         return ret;
540 static struct snd_soc_dai_ops tas2770_dai_ops = {
541         .digital_mute = tas2770_mute,
542         .hw_params  = tas2770_hw_params,
543         .set_fmt    = tas2770_set_dai_fmt,
544         .set_tdm_slot = tas2770_set_dai_tdm_slot,
545 };
547 #define TAS2770_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
548                 SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
550 #define TAS2770_RATES (SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |\
551                                                 SNDRV_PCM_RATE_96000 |\
552                                                 SNDRV_PCM_RATE_192000\
553                                                 )
555 static struct snd_soc_dai_driver tas2770_dai_driver[] = {
556         {
557                 .name = "tas2770 ASI1",
558                 .id = 0,
559                 .playback = {
560                         .stream_name    = "ASI1 Playback",
561                         .channels_min   = 2,
562                         .channels_max   = 2,
563                         .rates      = TAS2770_RATES,
564                         .formats    = TAS2770_FORMATS,
565                 },
566                 .capture = {
567                         .stream_name    = "ASI1 Capture",
568                         .channels_min   = 0,
569                         .channels_max   = 2,
570                         .rates          = TAS2770_RATES,
571                         .formats    = TAS2770_FORMATS,
572                 },
573                 .ops = &tas2770_dai_ops,
574                 .symmetric_rates = 1,
575         },
576 };
578 static int tas2770_codec_probe(struct snd_soc_codec *codec)
580         struct tas2770_priv *pTAS2770 = snd_soc_codec_get_drvdata(codec);
582         dev_err(pTAS2770->dev, "%s\n", __func__);
583         pTAS2770->codec = codec;
585         return 0;
588 static int tas2770_codec_remove(struct snd_soc_codec *codec)
590         return 0;
593 static DECLARE_TLV_DB_SCALE(tas2770_digital_tlv, 1100, 50, 0);
594 static DECLARE_TLV_DB_SCALE(tas2770_playback_volume, -12750, 50, 0);
596 static const struct snd_kcontrol_new tas2770_snd_controls[] = {
597         SOC_SINGLE_TLV("Amp Output Level", TAS2770_PlaybackConfigurationReg0,
598                 0, 0x14, 0,
599                 tas2770_digital_tlv),
600         SOC_SINGLE_TLV("Playback Volume", TAS2770_PlaybackConfigurationReg2,
601                 0, TAS2770_PlaybackConfigurationReg2_VOLMAX, 1,
602                 tas2770_playback_volume),
603 };
605 static struct snd_soc_codec_driver soc_codec_driver_tas2770 = {
606         .probe                  = tas2770_codec_probe,
607         .remove                 = tas2770_codec_remove,
608         .read                   = tas2770_codec_read,
609         .write                  = tas2770_codec_write,
610         .suspend                = tas2770_codec_suspend,
611         .resume                 = tas2770_codec_resume,
612         .component_driver = {
613                 .controls               = tas2770_snd_controls,
614                 .num_controls           = ARRAY_SIZE(tas2770_snd_controls),
615                 .dapm_widgets           = tas2770_dapm_widgets,
616                 .num_dapm_widgets       = ARRAY_SIZE(tas2770_dapm_widgets),
617                 .dapm_routes            = tas2770_audio_map,
618                 .num_dapm_routes        = ARRAY_SIZE(tas2770_audio_map),
619         },
620 };
622 int tas2770_register_codec(struct tas2770_priv *pTAS2770)
624         int nResult = 0;
626         dev_info(pTAS2770->dev, "%s, enter\n", __func__);
627         nResult = snd_soc_register_codec(pTAS2770->dev,
628                 &soc_codec_driver_tas2770,
629                 tas2770_dai_driver, ARRAY_SIZE(tas2770_dai_driver));
631         return nResult;
634 int tas2770_deregister_codec(struct tas2770_priv *pTAS2770)
636         snd_soc_unregister_codec(pTAS2770->dev);
638         return 0;
641 void tas2770_LoadConfig(struct tas2770_priv *pTAS2770)
643         int ret = 0;
645         pTAS2770->hw_reset(pTAS2770);
646         snd_soc_write(pTAS2770->codec, TAS2770_SoftwareReset,
647                         TAS2770_SoftwareReset_SoftwareReset_Reset);
649         ret = tas2770_set_slot(pTAS2770->codec, pTAS2770->mnSlot_width);
650         if (ret < 0)
651                 goto end;
653         ret = tas2770_set_fmt(pTAS2770, pTAS2770->mnASIFormat);
654         if (ret < 0)
655                 goto end;
657         ret = tas2770_set_bitwidth(pTAS2770, pTAS2770->mnCh_size);
658         if (ret < 0)
659                 goto end;
661         ret = tas2770_set_samplerate(pTAS2770, pTAS2770->mnSamplingRate);
662         if (ret < 0)
663                 goto end;
665         ret = tas2770_set_power_state(pTAS2770, pTAS2770->mnPowerState);
667 end:
668 /* power up failed, restart later */
669         if (ret < 0)
670                 schedule_delayed_work(&pTAS2770->irq_work,
671                                 msecs_to_jiffies(1000));
674 MODULE_AUTHOR("Texas Instruments Inc.");
675 MODULE_DESCRIPTION("TAS2770 ALSA SOC Smart Amplifier driver");
676 MODULE_LICENSE("GPL v2");
677 #endif /* CONFIG_TAS2770_CODEC */