]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - tas2770sw-android/tas2770sw-android.git/blob - tas2770-codec.c
295e3bcf144976a4116df739f5677a3d44afde9f
[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__);
111         pTAS2770->runtime_suspend(pTAS2770);
113         mutex_unlock(&pTAS2770->codec_lock);
114         return ret;
117 static int tas2770_codec_resume(struct snd_soc_codec *codec)
119         struct tas2770_priv *pTAS2770 = snd_soc_codec_get_drvdata(codec);
120         int ret = 0;
122         mutex_lock(&pTAS2770->codec_lock);
124         dev_dbg(pTAS2770->dev, "%s\n", __func__);
125         pTAS2770->runtime_resume(pTAS2770);
127         mutex_unlock(&pTAS2770->codec_lock);
128         return ret;
131 static const char * const tas2770_ASI1_src[] = {
132         "I2C offset", "Left", "Right", "LeftRightDiv2",
133 };
135 static SOC_ENUM_SINGLE_DECL(
136         tas2770_ASI1_src_enum, TAS2770_TDMConfigurationReg2,
137         4, tas2770_ASI1_src);
139 static const struct snd_kcontrol_new tas2770_asi1_mux =
140         SOC_DAPM_ENUM("ASI1 Source", tas2770_ASI1_src_enum);
142 static int tas2770_set_power_state(struct tas2770_priv *pTAS2770, int state)
144         struct snd_soc_codec *codec = pTAS2770->codec;
146         switch (state) {
147         case TAS2770_POWER_ACTIVE:
148                 snd_soc_update_bits(codec, TAS2770_PowerControl,
149                         TAS2770_PowerControl_OperationalMode10_Mask,
150                         TAS2770_PowerControl_OperationalMode10_Active);
151                 pTAS2770->mnPowerState = TAS2770_POWER_ACTIVE;
152                 pTAS2770->enableIRQ(pTAS2770, true);
153                 break;
155         case TAS2770_POWER_MUTE:
156                 snd_soc_update_bits(codec, TAS2770_PowerControl,
157                         TAS2770_PowerControl_OperationalMode10_Mask,
158                         TAS2770_PowerControl_OperationalMode10_Mute);
159                 pTAS2770->mnPowerState = TAS2770_POWER_MUTE;
160                 break;
162         case TAS2770_POWER_SHUTDOWN:
163                 snd_soc_update_bits(codec, TAS2770_PowerControl,
164                         TAS2770_PowerControl_OperationalMode10_Mask,
165                         TAS2770_PowerControl_OperationalMode10_Shutdown);
166                 pTAS2770->enableIRQ(pTAS2770, false);
167                 pTAS2770->mnPowerState = TAS2770_POWER_SHUTDOWN;
168                 break;
170         default:
171                 dev_err(pTAS2770->dev, "wrong power state setting %d\n", state);
173         }
175         pTAS2770->mnPowerState = state;
176         return 0;
179 static int tas2770_dac_event(struct snd_soc_dapm_widget *w,
180                         struct snd_kcontrol *kcontrol, int event)
182         struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
183         struct tas2770_priv *pTAS2770 = snd_soc_codec_get_drvdata(codec);
185         mutex_lock(&pTAS2770->codec_lock);
187         switch (event) {
188         case SND_SOC_DAPM_POST_PMU:
189                 tas2770_set_power_state(pTAS2770, TAS2770_POWER_MUTE);
190                 break;
191         case SND_SOC_DAPM_PRE_PMD:
192                 tas2770_set_power_state(pTAS2770, TAS2770_POWER_SHUTDOWN);
193                 break;
195         }
197         mutex_unlock(&pTAS2770->codec_lock);
198         return 0;
201 static const struct snd_kcontrol_new isense_switch =
202         SOC_DAPM_SINGLE("Switch", TAS2770_PowerControl, 3, 1, 1);
203 static const struct snd_kcontrol_new vsense_switch =
204         SOC_DAPM_SINGLE("Switch", TAS2770_PowerControl, 2, 1, 1);
206 static const struct snd_soc_dapm_widget tas2770_dapm_widgets[] = {
207         SND_SOC_DAPM_AIF_IN("ASI1", "ASI1 Playback", 0, SND_SOC_NOPM, 0, 0),
208         SND_SOC_DAPM_MUX("ASI1 Sel", SND_SOC_NOPM, 0, 0,
209                                 &tas2770_asi1_mux),
210         SND_SOC_DAPM_SWITCH("ISENSE", TAS2770_PowerControl, 3, 1,
211                         &isense_switch),
212         SND_SOC_DAPM_SWITCH("VSENSE", TAS2770_PowerControl, 2, 1,
213                         &vsense_switch),
214         SND_SOC_DAPM_DAC_E("DAC", NULL, SND_SOC_NOPM, 0, 0, tas2770_dac_event,
215         SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
216         SND_SOC_DAPM_OUTPUT("OUT"),
217         SND_SOC_DAPM_SIGGEN("VMON"),
218         SND_SOC_DAPM_SIGGEN("IMON")
219 };
221 static const struct snd_soc_dapm_route tas2770_audio_map[] = {
222         {"ASI1 Sel", "I2C offset", "ASI1"},
223         {"ASI1 Sel", "Left", "ASI1"},
224         {"ASI1 Sel", "Right", "ASI1"},
225         {"ASI1 Sel", "LeftRightDiv2", "ASI1"},
226         {"DAC", NULL, "ASI1 Sel"},
227         {"OUT", NULL, "DAC"},
228         {"ISENSE", "Switch", "IMON"},
229         {"VSENSE", "Switch", "VMON"},
230 };
233 static int tas2770_mute(struct snd_soc_dai *dai, int mute)
235         struct snd_soc_codec *codec = dai->codec;
236         struct tas2770_priv *pTAS2770 = snd_soc_codec_get_drvdata(codec);
237         dev_dbg(pTAS2770->dev, "%s\n", __func__);
239         mutex_lock(&pTAS2770->codec_lock);
240         if (mute) {
241                 tas2770_set_power_state(pTAS2770, TAS2770_POWER_MUTE);
242         } else {
243                 tas2770_set_power_state(pTAS2770, TAS2770_POWER_ACTIVE);
244         }
245         mutex_unlock(&pTAS2770->codec_lock);
246         return 0;
249 static int tas2770_set_bitwidth(struct tas2770_priv *pTAS2770, int bitwidth)
251         switch (bitwidth) {
252         case SNDRV_PCM_FORMAT_S16_LE:
253                 snd_soc_update_bits(pTAS2770->codec,
254                         TAS2770_TDMConfigurationReg2,
255                         TAS2770_TDMConfigurationReg2_RXWLEN32_Mask,
256                         TAS2770_TDMConfigurationReg2_RXWLEN32_16Bits);
257                         /* If machine driver did not call set slot width */
258                 if (pTAS2770->mnSlot_width == 0)
259                         tas2770_set_slot(pTAS2770->codec, 16);
260                 pTAS2770->mnVmon_slot_no = pTAS2770->mnImon_slot_no + 2;
261                 break;
262         case SNDRV_PCM_FORMAT_S24_LE:
263                 snd_soc_update_bits(pTAS2770->codec,
264                         TAS2770_TDMConfigurationReg2,
265                         TAS2770_TDMConfigurationReg2_RXWLEN32_Mask,
266                         TAS2770_TDMConfigurationReg2_RXWLEN32_24Bits);
267                 if (pTAS2770->mnSlot_width == 0)
268                         tas2770_set_slot(pTAS2770->codec, 32);
269                 pTAS2770->mnVmon_slot_no = pTAS2770->mnImon_slot_no + 4;
270                 break;
271         case SNDRV_PCM_FORMAT_S32_LE:
272                 snd_soc_update_bits(pTAS2770->codec,
273                         TAS2770_TDMConfigurationReg2,
274                         TAS2770_TDMConfigurationReg2_RXWLEN32_Mask,
275                         TAS2770_TDMConfigurationReg2_RXWLEN32_32Bits);
276                 if (pTAS2770->mnSlot_width == 0)
277                         tas2770_set_slot(pTAS2770->codec, 32);
278                 pTAS2770->mnVmon_slot_no = pTAS2770->mnImon_slot_no + 4;
279                 break;
281         default:
282                 dev_dbg(pTAS2770->dev, "Not supported params format\n");
283                 return -EINVAL;
284         }
286         pTAS2770->mnCh_size = bitwidth;
287         dev_dbg(pTAS2770->dev, "mnCh_size: %d\n", pTAS2770->mnCh_size);
289         snd_soc_update_bits(pTAS2770->codec,
290                 TAS2770_TDMConfigurationReg5,
291                 TAS2770_TDMConfigurationReg5_VSNSTX_Mask |
292                 TAS2770_TDMConfigurationReg5_VSNSSLOT50_Mask,
293                 TAS2770_TDMConfigurationReg5_VSNSTX_Enable |
294                 pTAS2770->mnVmon_slot_no);
295         snd_soc_update_bits(pTAS2770->codec,
296                 TAS2770_TDMConfigurationReg6,
297                 TAS2770_TDMConfigurationReg6_ISNSTX_Mask |
298                 TAS2770_TDMConfigurationReg6_ISNSSLOT50_Mask,
299                 TAS2770_TDMConfigurationReg6_ISNSTX_Enable |
300                 pTAS2770->mnImon_slot_no);
302         return 0;
305 static int tas2770_set_samplerate(struct tas2770_priv *pTAS2770, int samplerate)
307         switch (samplerate) {
308         case 48000:
309                         snd_soc_update_bits(pTAS2770->codec,
310                                 TAS2770_TDMConfigurationReg0,
311                                 TAS2770_TDMConfigurationReg0_SAMPRATERAMP_Mask,
312                                 TAS2770_TDMConfigurationReg0_SAMPRATERAMP_48KHz);
313                         snd_soc_update_bits(pTAS2770->codec,
314                                 TAS2770_TDMConfigurationReg0,
315                                 TAS2770_TDMConfigurationReg0_SAMPRATE31_Mask,
316                                 TAS2770_TDMConfigurationReg0_SAMPRATE31_44_1_48kHz);
317                         break;
318         case 44100:
319                         snd_soc_update_bits(pTAS2770->codec,
320                                 TAS2770_TDMConfigurationReg0,
321                                 TAS2770_TDMConfigurationReg0_SAMPRATERAMP_Mask,
322                                 TAS2770_TDMConfigurationReg0_SAMPRATERAMP_44_1KHz);
323                         snd_soc_update_bits(pTAS2770->codec,
324                                 TAS2770_TDMConfigurationReg0,
325                                 TAS2770_TDMConfigurationReg0_SAMPRATE31_Mask,
326                                 TAS2770_TDMConfigurationReg0_SAMPRATE31_44_1_48kHz);
327                         break;
328         case 96000:
329                         snd_soc_update_bits(pTAS2770->codec,
330                                 TAS2770_TDMConfigurationReg0,
331                                 TAS2770_TDMConfigurationReg0_SAMPRATERAMP_Mask,
332                                 TAS2770_TDMConfigurationReg0_SAMPRATERAMP_48KHz);
333                         snd_soc_update_bits(pTAS2770->codec,
334                                 TAS2770_TDMConfigurationReg0,
335                                 TAS2770_TDMConfigurationReg0_SAMPRATE31_Mask,
336                                 TAS2770_TDMConfigurationReg0_SAMPRATE31_88_2_96kHz);
337                         break;
338         case 88200:
339                         snd_soc_update_bits(pTAS2770->codec,
340                                 TAS2770_TDMConfigurationReg0,
341                                 TAS2770_TDMConfigurationReg0_SAMPRATERAMP_Mask,
342                                 TAS2770_TDMConfigurationReg0_SAMPRATERAMP_44_1KHz);
343                         snd_soc_update_bits(pTAS2770->codec,
344                                 TAS2770_TDMConfigurationReg0,
345                                 TAS2770_TDMConfigurationReg0_SAMPRATE31_Mask,
346                                 TAS2770_TDMConfigurationReg0_SAMPRATE31_88_2_96kHz);
347                         break;
348         case 19200:
349                         snd_soc_update_bits(pTAS2770->codec,
350                                 TAS2770_TDMConfigurationReg0,
351                                 TAS2770_TDMConfigurationReg0_SAMPRATERAMP_Mask,
352                                 TAS2770_TDMConfigurationReg0_SAMPRATERAMP_48KHz);
353                         snd_soc_update_bits(pTAS2770->codec,
354                                 TAS2770_TDMConfigurationReg0,
355                                 TAS2770_TDMConfigurationReg0_SAMPRATE31_Mask,
356                                 TAS2770_TDMConfigurationReg0_SAMPRATE31_176_4_192kHz);
357                         break;
358         case 17640:
359                         snd_soc_update_bits(pTAS2770->codec,
360                                 TAS2770_TDMConfigurationReg0,
361                                 TAS2770_TDMConfigurationReg0_SAMPRATERAMP_Mask,
362                                 TAS2770_TDMConfigurationReg0_SAMPRATERAMP_44_1KHz);
363                         snd_soc_update_bits(pTAS2770->codec,
364                                 TAS2770_TDMConfigurationReg0,
365                                 TAS2770_TDMConfigurationReg0_SAMPRATE31_Mask,
366                                 TAS2770_TDMConfigurationReg0_SAMPRATE31_176_4_192kHz);
367                         break;
368         default:
369                         dev_dbg(pTAS2770->dev, "%s, unsupported sample rate\n", __func__);
371         }
373         pTAS2770->mnSamplingRate = samplerate;
374         return 0;
377 static int tas2770_hw_params(struct snd_pcm_substream *substream,
378                 struct snd_pcm_hw_params *params,
379                 struct snd_soc_dai *dai)
381         struct snd_soc_codec *codec = dai->codec;
382         struct tas2770_priv *pTAS2770 = snd_soc_codec_get_drvdata(codec);
383         int ret = 0;
385         dev_dbg(pTAS2770->dev, "%s, format: %d\n", __func__,
386                 params_format(params));
388         mutex_lock(&pTAS2770->codec_lock);
390         ret = tas2770_set_bitwidth(pTAS2770, params_format(params));
391         if(ret < 0)
392                 return ret;
394         dev_dbg(pTAS2770->dev, "%s, sample rate: %d\n", __func__,
395                 params_rate(params));
397         ret = tas2770_set_samplerate(pTAS2770, params_rate(params));
399         mutex_unlock(&pTAS2770->codec_lock);
400         return ret;
403 static int tas2770_set_fmt(struct tas2770_priv *pTAS2770, unsigned int fmt)
405         u8 tdm_rx_start_slot = 0, asi_cfg_1 = 0;
406         int ret = 0;
407         int value = 0;
409         switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
410         case SND_SOC_DAIFMT_CBS_CFS:
411                 asi_cfg_1 = 0x00;
412                 break;
413         default:
414                 dev_err(pTAS2770->dev, "ASI format master is not found\n");
415                 ret = -EINVAL;
416         }
418         switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
419         case SND_SOC_DAIFMT_NB_NF:
420                 dev_dbg(pTAS2770->dev, "INV format: NBNF\n");
421                 asi_cfg_1 |= TAS2770_TDMConfigurationReg1_RXEDGE_Rising;
422                 break;
423         case SND_SOC_DAIFMT_IB_NF:
424                 dev_dbg(pTAS2770->dev, "INV format: IBNF\n");
425                 asi_cfg_1 |= TAS2770_TDMConfigurationReg1_RXEDGE_Falling;
426                 break;
427         default:
428                 dev_err(pTAS2770->dev, "ASI format Inverse is not found\n");
429                 ret = -EINVAL;
430         }
432         snd_soc_update_bits(pTAS2770->codec, TAS2770_TDMConfigurationReg1,
433                 TAS2770_TDMConfigurationReg1_RXEDGE_Mask,
434                 asi_cfg_1);
436         switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
437         case (SND_SOC_DAIFMT_I2S):
438                 tdm_rx_start_slot = 1;
439                 break;
440         case (SND_SOC_DAIFMT_DSP_A):
441         case (SND_SOC_DAIFMT_DSP_B):
442                 tdm_rx_start_slot = 1;
443                 break;
444         case (SND_SOC_DAIFMT_LEFT_J):
445                 tdm_rx_start_slot = 0;
446                 break;
447         default:
448         dev_err(pTAS2770->dev, "DAI Format is not found, fmt=0x%x\n", fmt);
449         ret = -EINVAL;
450                 break;
451         }
453         snd_soc_update_bits(pTAS2770->codec, TAS2770_TDMConfigurationReg1,
454                 TAS2770_TDMConfigurationReg1_RXOFFSET51_Mask,
455         (tdm_rx_start_slot << TAS2770_TDMConfigurationReg1_RXOFFSET51_Shift));
457         snd_soc_update_bits(pTAS2770->codec, TAS2770_TDMConfigurationReg3,
458                 TAS2770_TDMConfigurationReg3_RXSLOTLeft30_Mask,
459                 (pTAS2770->mnLeftSlot << TAS2770_TDMConfigurationReg3_RXSLOTLeft30_Shift));
460         snd_soc_update_bits(pTAS2770->codec, TAS2770_TDMConfigurationReg3,
461                 TAS2770_TDMConfigurationReg3_RXSLOTRight74_Mask,
462         (pTAS2770->mnRightSlot << TAS2770_TDMConfigurationReg3_RXSLOTRight74_Shift));
464         value = snd_soc_read(pTAS2770->codec, TAS2770_TDMConfigurationReg3);
465         dev_dbg(pTAS2770->dev, "slot value: 0x%x", value);
467         pTAS2770->mnASIFormat = fmt;
469         return 0;
472 static int tas2770_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
474         struct snd_soc_codec *codec = dai->codec;
475         struct tas2770_priv *pTAS2770 = snd_soc_codec_get_drvdata(codec);
476         int ret = 0;
478         dev_dbg(pTAS2770->dev, "%s, format=0x%x\n", __func__, fmt);
479         mutex_lock(&pTAS2770->codec_lock);
481         ret = tas2770_set_fmt(pTAS2770, fmt);
483         mutex_unlock(&pTAS2770->codec_lock);
484         return ret;
487 static int tas2770_set_slot(struct snd_soc_codec *codec, int slot_width)
489         int ret = 0;
490         struct tas2770_priv *pTAS2770 = snd_soc_codec_get_drvdata(codec);
492         switch (slot_width) {
493         case 16:
494         ret = snd_soc_update_bits(codec,
495                 TAS2770_TDMConfigurationReg2,
496                 TAS2770_TDMConfigurationReg2_RXSLEN10_Mask,
497                 TAS2770_TDMConfigurationReg2_RXSLEN10_16Bits);
498         break;
500         case 24:
501         ret = snd_soc_update_bits(codec,
502                 TAS2770_TDMConfigurationReg2,
503                 TAS2770_TDMConfigurationReg2_RXSLEN10_Mask,
504                 TAS2770_TDMConfigurationReg2_RXSLEN10_24Bits);
505         break;
507         case 32:
508         ret = snd_soc_update_bits(codec,
509                 TAS2770_TDMConfigurationReg2,
510                 TAS2770_TDMConfigurationReg2_RXSLEN10_Mask,
511                 TAS2770_TDMConfigurationReg2_RXSLEN10_32Bits);
512         break;
514         case 0:
515         /* Do not change slot width */
516         break;
518         default:
519                 dev_dbg(pTAS2770->dev, "slot width not supported");
520                 ret = -EINVAL;
521         }
523         if (ret >= 0)
524                 pTAS2770->mnSlot_width = slot_width;
526         return ret;
529 static int tas2770_set_dai_tdm_slot(struct snd_soc_dai *dai,
530                 unsigned int tx_mask, unsigned int rx_mask,
531                 int slots, int slot_width)
533         int ret = 0;
534         struct snd_soc_codec *codec = dai->codec;
535         struct tas2770_priv *pTAS2770 = snd_soc_codec_get_drvdata(codec);
537         dev_dbg(pTAS2770->dev, "%s, tx_mask:%d, rx_mask:%d, slots:%d, slot_width:%d",
538                         __func__, tx_mask, rx_mask, slots, slot_width);
540         mutex_lock(&pTAS2770->codec_lock);
541         ret = tas2770_set_slot(codec, slot_width);
542         mutex_unlock(&pTAS2770->codec_lock);
544         return ret;
547 static struct snd_soc_dai_ops tas2770_dai_ops = {
548         .digital_mute = tas2770_mute,
549         .hw_params  = tas2770_hw_params,
550         .set_fmt    = tas2770_set_dai_fmt,
551         .set_tdm_slot = tas2770_set_dai_tdm_slot,
552 };
554 #define TAS2770_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
555                 SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
557 #define TAS2770_RATES (SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |\
558                                                 SNDRV_PCM_RATE_96000 |\
559                                                 SNDRV_PCM_RATE_192000\
560                                                 )
562 static struct snd_soc_dai_driver tas2770_dai_driver[] = {
563         {
564                 .name = "tas2770 ASI1",
565                 .id = 0,
566                 .playback = {
567                         .stream_name    = "ASI1 Playback",
568                         .channels_min   = 2,
569                         .channels_max   = 2,
570                         .rates      = TAS2770_RATES,
571                         .formats    = TAS2770_FORMATS,
572                 },
573                 .capture = {
574                         .stream_name    = "ASI1 Capture",
575                         .channels_min   = 0,
576                         .channels_max   = 2,
577                         .rates          = TAS2770_RATES,
578                         .formats    = TAS2770_FORMATS,
579                 },
580                 .ops = &tas2770_dai_ops,
581                 .symmetric_rates = 1,
582         },
583 };
585 static int tas2770_codec_probe(struct snd_soc_codec *codec)
587         struct tas2770_priv *pTAS2770 = snd_soc_codec_get_drvdata(codec);
589         dev_err(pTAS2770->dev, "%s\n", __func__);
590         pTAS2770->codec = codec;
592         return 0;
595 static int tas2770_codec_remove(struct snd_soc_codec *codec)
597         return 0;
600 static DECLARE_TLV_DB_SCALE(tas2770_digital_tlv, 1100, 50, 0);
601 static DECLARE_TLV_DB_SCALE(tas2770_playback_volume, -12750, 50, 0);
603 static const struct snd_kcontrol_new tas2770_snd_controls[] = {
604         SOC_SINGLE_TLV("Amp Output Level", TAS2770_PlaybackConfigurationReg0,
605                 0, 0x14, 0,
606                 tas2770_digital_tlv),
607         SOC_SINGLE_TLV("Playback Volume", TAS2770_PlaybackConfigurationReg2,
608                 0, TAS2770_PlaybackConfigurationReg2_VOLMAX, 1,
609                 tas2770_playback_volume),
610 };
612 static struct snd_soc_codec_driver soc_codec_driver_tas2770 = {
613         .probe                  = tas2770_codec_probe,
614         .remove                 = tas2770_codec_remove,
615         .read                   = tas2770_codec_read,
616         .write                  = tas2770_codec_write,
617         .suspend                = tas2770_codec_suspend,
618         .resume                 = tas2770_codec_resume,
619         .component_driver = {
620                 .controls               = tas2770_snd_controls,
621                 .num_controls           = ARRAY_SIZE(tas2770_snd_controls),
622                 .dapm_widgets           = tas2770_dapm_widgets,
623                 .num_dapm_widgets       = ARRAY_SIZE(tas2770_dapm_widgets),
624                 .dapm_routes            = tas2770_audio_map,
625                 .num_dapm_routes        = ARRAY_SIZE(tas2770_audio_map),
626         },
627 };
629 int tas2770_register_codec(struct tas2770_priv *pTAS2770)
631         int nResult = 0;
633         dev_info(pTAS2770->dev, "%s, enter\n", __func__);
634         nResult = snd_soc_register_codec(pTAS2770->dev,
635                 &soc_codec_driver_tas2770,
636                 tas2770_dai_driver, ARRAY_SIZE(tas2770_dai_driver));
638         return nResult;
641 int tas2770_deregister_codec(struct tas2770_priv *pTAS2770)
643         snd_soc_unregister_codec(pTAS2770->dev);
645         return 0;
648 void tas2770_LoadConfig(struct tas2770_priv *pTAS2770)
650         int ret = 0;
652         pTAS2770->hw_reset(pTAS2770);
653         snd_soc_write(pTAS2770->codec, TAS2770_SoftwareReset,
654                         TAS2770_SoftwareReset_SoftwareReset_Reset);
656         ret = tas2770_set_slot(pTAS2770->codec, pTAS2770->mnSlot_width);
657         if (ret < 0)
658                 goto end;
660         ret = tas2770_set_fmt(pTAS2770, pTAS2770->mnASIFormat);
661         if (ret < 0)
662                 goto end;
664         ret = tas2770_set_bitwidth(pTAS2770, pTAS2770->mnCh_size);
665         if (ret < 0)
666                 goto end;
668         ret = tas2770_set_samplerate(pTAS2770, pTAS2770->mnSamplingRate);
669         if (ret < 0)
670                 goto end;
672         ret = tas2770_set_power_state(pTAS2770, pTAS2770->mnPowerState);
674 end:
675 /* power up failed, restart later */
676         if (ret < 0)
677                 schedule_delayed_work(&pTAS2770->irq_work,
678                                 msecs_to_jiffies(1000));
681 MODULE_AUTHOR("Texas Instruments Inc.");
682 MODULE_DESCRIPTION("TAS2770 ALSA SOC Smart Amplifier driver");
683 MODULE_LICENSE("GPL v2");
684 #endif /* CONFIG_TAS2770_CODEC */