Add support to IRQ
[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                 break;
254         case SNDRV_PCM_FORMAT_S24_LE:
255                         snd_soc_update_bits(pTAS2770->codec,
256                         TAS2770_TDMConfigurationReg2,
257                         TAS2770_TDMConfigurationReg2_RXWLEN32_Mask,
258                         TAS2770_TDMConfigurationReg2_RXWLEN32_24Bits);
259                         if (pTAS2770->mnSlot_width == 0)
260                                 tas2770_set_slot(pTAS2770->codec, 32);
261                 break;
262         case SNDRV_PCM_FORMAT_S32_LE:
263                         snd_soc_update_bits(pTAS2770->codec,
264                         TAS2770_TDMConfigurationReg2,
265                         TAS2770_TDMConfigurationReg2_RXWLEN32_Mask,
266                         TAS2770_TDMConfigurationReg2_RXWLEN32_32Bits);
267                         if (pTAS2770->mnSlot_width == 0)
268                                 tas2770_set_slot(pTAS2770->codec, 32);
269                 break;
271         default:
272                 dev_dbg(pTAS2770->dev, "Not supported params format\n");
273                 return -EINVAL;
274         }
276         pTAS2770->mnCh_size = bitwidth;
277         dev_dbg(pTAS2770->dev, "mnCh_size: %d\n", pTAS2770->mnCh_size);
279         snd_soc_update_bits(pTAS2770->codec,
280                 TAS2770_TDMConfigurationReg5,
281                 TAS2770_TDMConfigurationReg5_VSNSTX_Mask |
282                 TAS2770_TDMConfigurationReg5_VSNSSLOT50_Mask,
283                 TAS2770_TDMConfigurationReg5_VSNSTX_Enable |
284                 pTAS2770->mnVmon_slot_no);
285         snd_soc_update_bits(pTAS2770->codec,
286                 TAS2770_TDMConfigurationReg6,
287                 TAS2770_TDMConfigurationReg6_ISNSTX_Mask |
288                 TAS2770_TDMConfigurationReg6_ISNSSLOT50_Mask,
289                 TAS2770_TDMConfigurationReg6_ISNSTX_Enable |
290                 pTAS2770->mnImon_slot_no);
292         return 0;
295 static int tas2770_set_samplerate(struct tas2770_priv *pTAS2770, int samplerate)
297         switch (samplerate) {
298         case 48000:
299                         snd_soc_update_bits(pTAS2770->codec,
300                                 TAS2770_TDMConfigurationReg0,
301                                 TAS2770_TDMConfigurationReg0_SAMPRATERAMP_Mask,
302                                 TAS2770_TDMConfigurationReg0_SAMPRATERAMP_48KHz);
303                         snd_soc_update_bits(pTAS2770->codec,
304                                 TAS2770_TDMConfigurationReg0,
305                                 TAS2770_TDMConfigurationReg0_SAMPRATE31_Mask,
306                                 TAS2770_TDMConfigurationReg0_SAMPRATE31_44_1_48kHz);
307                         break;
308         case 44100:
309                         snd_soc_update_bits(pTAS2770->codec,
310                                 TAS2770_TDMConfigurationReg0,
311                                 TAS2770_TDMConfigurationReg0_SAMPRATERAMP_Mask,
312                                 TAS2770_TDMConfigurationReg0_SAMPRATERAMP_44_1KHz);
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 96000:
319                         snd_soc_update_bits(pTAS2770->codec,
320                                 TAS2770_TDMConfigurationReg0,
321                                 TAS2770_TDMConfigurationReg0_SAMPRATERAMP_Mask,
322                                 TAS2770_TDMConfigurationReg0_SAMPRATERAMP_48KHz);
323                         snd_soc_update_bits(pTAS2770->codec,
324                                 TAS2770_TDMConfigurationReg0,
325                                 TAS2770_TDMConfigurationReg0_SAMPRATE31_Mask,
326                                 TAS2770_TDMConfigurationReg0_SAMPRATE31_88_2_96kHz);
327                         break;
328         case 88200:
329                         snd_soc_update_bits(pTAS2770->codec,
330                                 TAS2770_TDMConfigurationReg0,
331                                 TAS2770_TDMConfigurationReg0_SAMPRATERAMP_Mask,
332                                 TAS2770_TDMConfigurationReg0_SAMPRATERAMP_44_1KHz);
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 19200:
339                         snd_soc_update_bits(pTAS2770->codec,
340                                 TAS2770_TDMConfigurationReg0,
341                                 TAS2770_TDMConfigurationReg0_SAMPRATERAMP_Mask,
342                                 TAS2770_TDMConfigurationReg0_SAMPRATERAMP_48KHz);
343                         snd_soc_update_bits(pTAS2770->codec,
344                                 TAS2770_TDMConfigurationReg0,
345                                 TAS2770_TDMConfigurationReg0_SAMPRATE31_Mask,
346                                 TAS2770_TDMConfigurationReg0_SAMPRATE31_176_4_192kHz);
347                         break;
348         case 17640:
349                         snd_soc_update_bits(pTAS2770->codec,
350                                 TAS2770_TDMConfigurationReg0,
351                                 TAS2770_TDMConfigurationReg0_SAMPRATERAMP_Mask,
352                                 TAS2770_TDMConfigurationReg0_SAMPRATERAMP_44_1KHz);
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         default:
359                         dev_dbg(pTAS2770->dev, "%s, unsupported sample rate\n", __func__);
361         }
363         pTAS2770->mnSamplingRate = samplerate;
364         return 0;
367 static int tas2770_hw_params(struct snd_pcm_substream *substream,
368                 struct snd_pcm_hw_params *params,
369                 struct snd_soc_dai *dai)
371         struct snd_soc_codec *codec = dai->codec;
372         struct tas2770_priv *pTAS2770 = snd_soc_codec_get_drvdata(codec);
373         int ret = 0;
375         dev_dbg(pTAS2770->dev, "%s, format: %d\n", __func__,
376                 params_format(params));
378         mutex_lock(&pTAS2770->codec_lock);
380         ret = tas2770_set_bitwidth(pTAS2770, params_format(params));
381         if(ret < 0)
382                 return ret;
384         dev_dbg(pTAS2770->dev, "%s, sample rate: %d\n", __func__,
385                 params_rate(params));
387         ret = tas2770_set_samplerate(pTAS2770, params_rate(params));
389         mutex_unlock(&pTAS2770->codec_lock);
390         return ret;
393 static int tas2770_set_fmt(struct tas2770_priv *pTAS2770, unsigned int fmt)
395         u8 tdm_rx_start_slot = 0, asi_cfg_1 = 0;
396         int ret = 0;
397         int value = 0;
399         switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
400         case SND_SOC_DAIFMT_CBS_CFS:
401                 asi_cfg_1 = 0x00;
402                 break;
403         default:
404                 dev_err(pTAS2770->dev, "ASI format master is not found\n");
405                 ret = -EINVAL;
406         }
408         switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
409         case SND_SOC_DAIFMT_NB_NF:
410                 dev_dbg(pTAS2770->dev, "INV format: NBNF\n");
411                 asi_cfg_1 |= TAS2770_TDMConfigurationReg1_RXEDGE_Rising;
412                 break;
413         case SND_SOC_DAIFMT_IB_NF:
414                 dev_dbg(pTAS2770->dev, "INV format: IBNF\n");
415                 asi_cfg_1 |= TAS2770_TDMConfigurationReg1_RXEDGE_Falling;
416                 break;
417         default:
418                 dev_err(pTAS2770->dev, "ASI format Inverse is not found\n");
419                 ret = -EINVAL;
420         }
422         snd_soc_update_bits(pTAS2770->codec, TAS2770_TDMConfigurationReg1,
423                 TAS2770_TDMConfigurationReg1_RXEDGE_Mask,
424                 asi_cfg_1);
426         switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
427         case (SND_SOC_DAIFMT_I2S):
428                 tdm_rx_start_slot = 1;
429                 break;
430         case (SND_SOC_DAIFMT_DSP_A):
431         case (SND_SOC_DAIFMT_DSP_B):
432                 tdm_rx_start_slot = 1;
433                 break;
434         case (SND_SOC_DAIFMT_LEFT_J):
435                 tdm_rx_start_slot = 0;
436                 break;
437         default:
438         dev_err(pTAS2770->dev, "DAI Format is not found, fmt=0x%x\n", fmt);
439         ret = -EINVAL;
440                 break;
441         }
443         snd_soc_update_bits(pTAS2770->codec, TAS2770_TDMConfigurationReg1,
444                 TAS2770_TDMConfigurationReg1_RXOFFSET51_Mask,
445         (tdm_rx_start_slot << TAS2770_TDMConfigurationReg1_RXOFFSET51_Shift));
447         snd_soc_update_bits(pTAS2770->codec, TAS2770_TDMConfigurationReg3,
448                 TAS2770_TDMConfigurationReg3_RXSLOTLeft30_Mask,
449                 (pTAS2770->mnLeftSlot << TAS2770_TDMConfigurationReg3_RXSLOTLeft30_Shift));
450         snd_soc_update_bits(pTAS2770->codec, TAS2770_TDMConfigurationReg3,
451                 TAS2770_TDMConfigurationReg3_RXSLOTRight74_Mask,
452         (pTAS2770->mnRightSlot << TAS2770_TDMConfigurationReg3_RXSLOTRight74_Shift));
454         value = snd_soc_read(pTAS2770->codec, TAS2770_TDMConfigurationReg3);
455         dev_dbg(pTAS2770->dev, "slot value: 0x%x", value);
457         pTAS2770->mnASIFormat = fmt;
459         return 0;
462 static int tas2770_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
464         struct snd_soc_codec *codec = dai->codec;
465         struct tas2770_priv *pTAS2770 = snd_soc_codec_get_drvdata(codec);
466         int ret = 0;
468         dev_dbg(pTAS2770->dev, "%s, format=0x%x\n", __func__, fmt);
469         mutex_lock(&pTAS2770->codec_lock);
471         ret = tas2770_set_fmt(pTAS2770, fmt);
473         mutex_unlock(&pTAS2770->codec_lock);
474         return ret;
477 static int tas2770_set_slot(struct snd_soc_codec *codec, int slot_width)
479         int ret = 0;
480         struct tas2770_priv *pTAS2770 = snd_soc_codec_get_drvdata(codec);
482         switch (slot_width) {
483         case 16:
484         ret = snd_soc_update_bits(codec,
485                 TAS2770_TDMConfigurationReg2,
486                 TAS2770_TDMConfigurationReg2_RXSLEN10_Mask,
487                 TAS2770_TDMConfigurationReg2_RXSLEN10_16Bits);
488         break;
490         case 24:
491         ret = snd_soc_update_bits(codec,
492                 TAS2770_TDMConfigurationReg2,
493                 TAS2770_TDMConfigurationReg2_RXSLEN10_Mask,
494                 TAS2770_TDMConfigurationReg2_RXSLEN10_24Bits);
495         break;
497         case 32:
498         ret = snd_soc_update_bits(codec,
499                 TAS2770_TDMConfigurationReg2,
500                 TAS2770_TDMConfigurationReg2_RXSLEN10_Mask,
501                 TAS2770_TDMConfigurationReg2_RXSLEN10_32Bits);
502         break;
504         case 0:
505         /* Do not change slot width */
506         break;
508         default:
509                 dev_dbg(pTAS2770->dev, "slot width not supported");
510                 ret = -EINVAL;
511         }
513         if (ret >= 0)
514                 pTAS2770->mnSlot_width = slot_width;
516         return ret;
519 static int tas2770_set_dai_tdm_slot(struct snd_soc_dai *dai,
520                 unsigned int tx_mask, unsigned int rx_mask,
521                 int slots, int slot_width)
523         int ret = 0;
524         struct snd_soc_codec *codec = dai->codec;
525         struct tas2770_priv *pTAS2770 = snd_soc_codec_get_drvdata(codec);
527         dev_dbg(pTAS2770->dev, "%s, tx_mask:%d, rx_mask:%d, slots:%d, slot_width:%d",
528                         __func__, tx_mask, rx_mask, slots, slot_width);
530         mutex_lock(&pTAS2770->codec_lock);
531         ret = tas2770_set_slot(codec, slot_width);
532         mutex_unlock(&pTAS2770->codec_lock);
534         return ret;
537 static struct snd_soc_dai_ops tas2770_dai_ops = {
538         .digital_mute = tas2770_mute,
539         .hw_params  = tas2770_hw_params,
540         .set_fmt    = tas2770_set_dai_fmt,
541         .set_tdm_slot = tas2770_set_dai_tdm_slot,
542 };
544 #define TAS2770_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
545                 SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
547 #define TAS2770_RATES (SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |\
548                                                 SNDRV_PCM_RATE_96000 |\
549                                                 SNDRV_PCM_RATE_192000\
550                                                 )
552 static struct snd_soc_dai_driver tas2770_dai_driver[] = {
553         {
554                 .name = "tas2770 ASI1",
555                 .id = 0,
556                 .playback = {
557                         .stream_name    = "ASI1 Playback",
558                         .channels_min   = 2,
559                         .channels_max   = 2,
560                         .rates      = TAS2770_RATES,
561                         .formats    = TAS2770_FORMATS,
562                 },
563                 .capture = {
564                         .stream_name    = "ASI1 Capture",
565                         .channels_min   = 0,
566                         .channels_max   = 2,
567                         .rates          = TAS2770_RATES,
568                         .formats    = TAS2770_FORMATS,
569                 },
570                 .ops = &tas2770_dai_ops,
571                 .symmetric_rates = 1,
572         },
573 };
575 static int tas2770_codec_probe(struct snd_soc_codec *codec)
577         struct tas2770_priv *pTAS2770 = snd_soc_codec_get_drvdata(codec);
579         dev_err(pTAS2770->dev, "%s\n", __func__);
580         pTAS2770->codec = codec;
582         return 0;
585 static int tas2770_codec_remove(struct snd_soc_codec *codec)
587         return 0;
590 static DECLARE_TLV_DB_SCALE(tas2770_digital_tlv, 1100, 50, 0);
591 static DECLARE_TLV_DB_SCALE(tas2770_playback_volume, -12750, 50, 0);
593 static const struct snd_kcontrol_new tas2770_snd_controls[] = {
594         SOC_SINGLE_TLV("Amp Output Level", TAS2770_PlaybackConfigurationReg0,
595                 0, 0x14, 0,
596                 tas2770_digital_tlv),
597         SOC_SINGLE_TLV("Playback Volume", TAS2770_PlaybackConfigurationReg2,
598                 0, TAS2770_PlaybackConfigurationReg2_VOLMAX, 1,
599                 tas2770_playback_volume),
600 };
602 static struct snd_soc_codec_driver soc_codec_driver_tas2770 = {
603         .probe                  = tas2770_codec_probe,
604         .remove                 = tas2770_codec_remove,
605         .read                   = tas2770_codec_read,
606         .write                  = tas2770_codec_write,
607         .suspend                = tas2770_codec_suspend,
608         .resume                 = tas2770_codec_resume,
609         .component_driver = {
610                 .controls               = tas2770_snd_controls,
611                 .num_controls           = ARRAY_SIZE(tas2770_snd_controls),
612                 .dapm_widgets           = tas2770_dapm_widgets,
613                 .num_dapm_widgets       = ARRAY_SIZE(tas2770_dapm_widgets),
614                 .dapm_routes            = tas2770_audio_map,
615                 .num_dapm_routes        = ARRAY_SIZE(tas2770_audio_map),
616         },
617 };
619 int tas2770_register_codec(struct tas2770_priv *pTAS2770)
621         int nResult = 0;
623         dev_info(pTAS2770->dev, "%s, enter\n", __func__);
624         nResult = snd_soc_register_codec(pTAS2770->dev,
625                 &soc_codec_driver_tas2770,
626                 tas2770_dai_driver, ARRAY_SIZE(tas2770_dai_driver));
628         return nResult;
631 int tas2770_deregister_codec(struct tas2770_priv *pTAS2770)
633         snd_soc_unregister_codec(pTAS2770->dev);
635         return 0;
638 void tas2770_LoadConfig(struct tas2770_priv *pTAS2770)
640         int ret = 0;
642         pTAS2770->hw_reset(pTAS2770);
643         snd_soc_write(pTAS2770->codec, TAS2770_SoftwareReset,
644                         TAS2770_SoftwareReset_SoftwareReset_Reset);
646         ret = tas2770_set_slot(pTAS2770->codec, pTAS2770->mnSlot_width);
647         if (ret < 0)
648                 goto end;
650         ret = tas2770_set_fmt(pTAS2770, pTAS2770->mnASIFormat);
651         if (ret < 0)
652                 goto end;
654         ret = tas2770_set_bitwidth(pTAS2770, pTAS2770->mnCh_size);
655         if (ret < 0)
656                 goto end;
658         ret = tas2770_set_samplerate(pTAS2770, pTAS2770->mnSamplingRate);
659         if (ret < 0)
660                 goto end;
662         ret = tas2770_set_power_state(pTAS2770, pTAS2770->mnPowerState);
664 end:
665 /* power up failed, restart later */
666         if (ret < 0)
667                 schedule_delayed_work(&pTAS2770->irq_work,
668                                 msecs_to_jiffies(1000));
671 MODULE_AUTHOR("Texas Instruments Inc.");
672 MODULE_DESCRIPTION("TAS2770 ALSA SOC Smart Amplifier driver");
673 MODULE_LICENSE("GPL v2");
674 #endif /* CONFIG_TAS2770_CODEC */