]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - tas2770sw-android/tas2770sw-android.git/blob - tas2770-codec.c
Remove improper power state setting
[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         return 0;
178 static int tas2770_dac_event(struct snd_soc_dapm_widget *w,
179                         struct snd_kcontrol *kcontrol, int event)
181         struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
182         struct tas2770_priv *pTAS2770 = snd_soc_codec_get_drvdata(codec);
184         mutex_lock(&pTAS2770->codec_lock);
186         switch (event) {
187         case SND_SOC_DAPM_POST_PMU:
188                 tas2770_set_power_state(pTAS2770, TAS2770_POWER_MUTE);
189                 break;
190         case SND_SOC_DAPM_PRE_PMD:
191                 tas2770_set_power_state(pTAS2770, TAS2770_POWER_SHUTDOWN);
192                 break;
194         }
196         mutex_unlock(&pTAS2770->codec_lock);
197         return 0;
200 static const struct snd_kcontrol_new isense_switch =
201         SOC_DAPM_SINGLE("Switch", TAS2770_PowerControl, 3, 1, 1);
202 static const struct snd_kcontrol_new vsense_switch =
203         SOC_DAPM_SINGLE("Switch", TAS2770_PowerControl, 2, 1, 1);
205 static const struct snd_soc_dapm_widget tas2770_dapm_widgets[] = {
206         SND_SOC_DAPM_AIF_IN("ASI1", "ASI1 Playback", 0, SND_SOC_NOPM, 0, 0),
207         SND_SOC_DAPM_MUX("ASI1 Sel", SND_SOC_NOPM, 0, 0,
208                                 &tas2770_asi1_mux),
209         SND_SOC_DAPM_SWITCH("ISENSE", TAS2770_PowerControl, 3, 1,
210                         &isense_switch),
211         SND_SOC_DAPM_SWITCH("VSENSE", TAS2770_PowerControl, 2, 1,
212                         &vsense_switch),
213         SND_SOC_DAPM_DAC_E("DAC", NULL, SND_SOC_NOPM, 0, 0, tas2770_dac_event,
214         SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
215         SND_SOC_DAPM_OUTPUT("OUT"),
216         SND_SOC_DAPM_SIGGEN("VMON"),
217         SND_SOC_DAPM_SIGGEN("IMON")
218 };
220 static const struct snd_soc_dapm_route tas2770_audio_map[] = {
221         {"ASI1 Sel", "I2C offset", "ASI1"},
222         {"ASI1 Sel", "Left", "ASI1"},
223         {"ASI1 Sel", "Right", "ASI1"},
224         {"ASI1 Sel", "LeftRightDiv2", "ASI1"},
225         {"DAC", NULL, "ASI1 Sel"},
226         {"OUT", NULL, "DAC"},
227         {"ISENSE", "Switch", "IMON"},
228         {"VSENSE", "Switch", "VMON"},
229 };
232 static int tas2770_mute(struct snd_soc_dai *dai, int mute)
234         struct snd_soc_codec *codec = dai->codec;
235         struct tas2770_priv *pTAS2770 = snd_soc_codec_get_drvdata(codec);
236         dev_dbg(pTAS2770->dev, "%s\n", __func__);
238         mutex_lock(&pTAS2770->codec_lock);
239         if (mute) {
240                 tas2770_set_power_state(pTAS2770, TAS2770_POWER_MUTE);
241         } else {
242                 tas2770_set_power_state(pTAS2770, TAS2770_POWER_ACTIVE);
243         }
244         mutex_unlock(&pTAS2770->codec_lock);
245         return 0;
248 static int tas2770_set_bitwidth(struct tas2770_priv *pTAS2770, int bitwidth)
250         switch (bitwidth) {
251         case SNDRV_PCM_FORMAT_S16_LE:
252                 snd_soc_update_bits(pTAS2770->codec,
253                         TAS2770_TDMConfigurationReg2,
254                         TAS2770_TDMConfigurationReg2_RXWLEN32_Mask,
255                         TAS2770_TDMConfigurationReg2_RXWLEN32_16Bits);
256                         /* If machine driver did not call set slot width */
257                 if (pTAS2770->mnSlot_width == 0)
258                         tas2770_set_slot(pTAS2770->codec, 16);
259                 pTAS2770->mnVmon_slot_no = pTAS2770->mnImon_slot_no + 2;
260                 break;
261         case SNDRV_PCM_FORMAT_S24_LE:
262                 snd_soc_update_bits(pTAS2770->codec,
263                         TAS2770_TDMConfigurationReg2,
264                         TAS2770_TDMConfigurationReg2_RXWLEN32_Mask,
265                         TAS2770_TDMConfigurationReg2_RXWLEN32_24Bits);
266                 if (pTAS2770->mnSlot_width == 0)
267                         tas2770_set_slot(pTAS2770->codec, 32);
268                 pTAS2770->mnVmon_slot_no = pTAS2770->mnImon_slot_no + 4;
269                 break;
270         case SNDRV_PCM_FORMAT_S32_LE:
271                 snd_soc_update_bits(pTAS2770->codec,
272                         TAS2770_TDMConfigurationReg2,
273                         TAS2770_TDMConfigurationReg2_RXWLEN32_Mask,
274                         TAS2770_TDMConfigurationReg2_RXWLEN32_32Bits);
275                 if (pTAS2770->mnSlot_width == 0)
276                         tas2770_set_slot(pTAS2770->codec, 32);
277                 pTAS2770->mnVmon_slot_no = pTAS2770->mnImon_slot_no + 4;
278                 break;
280         default:
281                 dev_dbg(pTAS2770->dev, "Not supported params format\n");
282                 return -EINVAL;
283         }
285         pTAS2770->mnCh_size = bitwidth;
286         dev_dbg(pTAS2770->dev, "mnCh_size: %d\n", pTAS2770->mnCh_size);
288         snd_soc_update_bits(pTAS2770->codec,
289                 TAS2770_TDMConfigurationReg5,
290                 TAS2770_TDMConfigurationReg5_VSNSTX_Mask |
291                 TAS2770_TDMConfigurationReg5_VSNSSLOT50_Mask,
292                 TAS2770_TDMConfigurationReg5_VSNSTX_Enable |
293                 pTAS2770->mnVmon_slot_no);
294         snd_soc_update_bits(pTAS2770->codec,
295                 TAS2770_TDMConfigurationReg6,
296                 TAS2770_TDMConfigurationReg6_ISNSTX_Mask |
297                 TAS2770_TDMConfigurationReg6_ISNSSLOT50_Mask,
298                 TAS2770_TDMConfigurationReg6_ISNSTX_Enable |
299                 pTAS2770->mnImon_slot_no);
301         return 0;
304 static int tas2770_set_samplerate(struct tas2770_priv *pTAS2770, int samplerate)
306         switch (samplerate) {
307         case 48000:
308                         snd_soc_update_bits(pTAS2770->codec,
309                                 TAS2770_TDMConfigurationReg0,
310                                 TAS2770_TDMConfigurationReg0_SAMPRATERAMP_Mask,
311                                 TAS2770_TDMConfigurationReg0_SAMPRATERAMP_48KHz);
312                         snd_soc_update_bits(pTAS2770->codec,
313                                 TAS2770_TDMConfigurationReg0,
314                                 TAS2770_TDMConfigurationReg0_SAMPRATE31_Mask,
315                                 TAS2770_TDMConfigurationReg0_SAMPRATE31_44_1_48kHz);
316                         break;
317         case 44100:
318                         snd_soc_update_bits(pTAS2770->codec,
319                                 TAS2770_TDMConfigurationReg0,
320                                 TAS2770_TDMConfigurationReg0_SAMPRATERAMP_Mask,
321                                 TAS2770_TDMConfigurationReg0_SAMPRATERAMP_44_1KHz);
322                         snd_soc_update_bits(pTAS2770->codec,
323                                 TAS2770_TDMConfigurationReg0,
324                                 TAS2770_TDMConfigurationReg0_SAMPRATE31_Mask,
325                                 TAS2770_TDMConfigurationReg0_SAMPRATE31_44_1_48kHz);
326                         break;
327         case 96000:
328                         snd_soc_update_bits(pTAS2770->codec,
329                                 TAS2770_TDMConfigurationReg0,
330                                 TAS2770_TDMConfigurationReg0_SAMPRATERAMP_Mask,
331                                 TAS2770_TDMConfigurationReg0_SAMPRATERAMP_48KHz);
332                         snd_soc_update_bits(pTAS2770->codec,
333                                 TAS2770_TDMConfigurationReg0,
334                                 TAS2770_TDMConfigurationReg0_SAMPRATE31_Mask,
335                                 TAS2770_TDMConfigurationReg0_SAMPRATE31_88_2_96kHz);
336                         break;
337         case 88200:
338                         snd_soc_update_bits(pTAS2770->codec,
339                                 TAS2770_TDMConfigurationReg0,
340                                 TAS2770_TDMConfigurationReg0_SAMPRATERAMP_Mask,
341                                 TAS2770_TDMConfigurationReg0_SAMPRATERAMP_44_1KHz);
342                         snd_soc_update_bits(pTAS2770->codec,
343                                 TAS2770_TDMConfigurationReg0,
344                                 TAS2770_TDMConfigurationReg0_SAMPRATE31_Mask,
345                                 TAS2770_TDMConfigurationReg0_SAMPRATE31_88_2_96kHz);
346                         break;
347         case 19200:
348                         snd_soc_update_bits(pTAS2770->codec,
349                                 TAS2770_TDMConfigurationReg0,
350                                 TAS2770_TDMConfigurationReg0_SAMPRATERAMP_Mask,
351                                 TAS2770_TDMConfigurationReg0_SAMPRATERAMP_48KHz);
352                         snd_soc_update_bits(pTAS2770->codec,
353                                 TAS2770_TDMConfigurationReg0,
354                                 TAS2770_TDMConfigurationReg0_SAMPRATE31_Mask,
355                                 TAS2770_TDMConfigurationReg0_SAMPRATE31_176_4_192kHz);
356                         break;
357         case 17640:
358                         snd_soc_update_bits(pTAS2770->codec,
359                                 TAS2770_TDMConfigurationReg0,
360                                 TAS2770_TDMConfigurationReg0_SAMPRATERAMP_Mask,
361                                 TAS2770_TDMConfigurationReg0_SAMPRATERAMP_44_1KHz);
362                         snd_soc_update_bits(pTAS2770->codec,
363                                 TAS2770_TDMConfigurationReg0,
364                                 TAS2770_TDMConfigurationReg0_SAMPRATE31_Mask,
365                                 TAS2770_TDMConfigurationReg0_SAMPRATE31_176_4_192kHz);
366                         break;
367         default:
368                         dev_dbg(pTAS2770->dev, "%s, unsupported sample rate\n", __func__);
370         }
372         pTAS2770->mnSamplingRate = samplerate;
373         return 0;
376 static int tas2770_hw_params(struct snd_pcm_substream *substream,
377                 struct snd_pcm_hw_params *params,
378                 struct snd_soc_dai *dai)
380         struct snd_soc_codec *codec = dai->codec;
381         struct tas2770_priv *pTAS2770 = snd_soc_codec_get_drvdata(codec);
382         int ret = 0;
384         dev_dbg(pTAS2770->dev, "%s, format: %d\n", __func__,
385                 params_format(params));
387         mutex_lock(&pTAS2770->codec_lock);
389         ret = tas2770_set_bitwidth(pTAS2770, params_format(params));
390         if(ret < 0)
391                 return ret;
393         dev_dbg(pTAS2770->dev, "%s, sample rate: %d\n", __func__,
394                 params_rate(params));
396         ret = tas2770_set_samplerate(pTAS2770, params_rate(params));
398         mutex_unlock(&pTAS2770->codec_lock);
399         return ret;
402 static int tas2770_set_fmt(struct tas2770_priv *pTAS2770, unsigned int fmt)
404         u8 tdm_rx_start_slot = 0, asi_cfg_1 = 0;
405         int ret = 0;
406         int value = 0;
408         switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
409         case SND_SOC_DAIFMT_CBS_CFS:
410                 asi_cfg_1 = 0x00;
411                 break;
412         default:
413                 dev_err(pTAS2770->dev, "ASI format master is not found\n");
414                 ret = -EINVAL;
415         }
417         switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
418         case SND_SOC_DAIFMT_NB_NF:
419                 dev_dbg(pTAS2770->dev, "INV format: NBNF\n");
420                 asi_cfg_1 |= TAS2770_TDMConfigurationReg1_RXEDGE_Rising;
421                 break;
422         case SND_SOC_DAIFMT_IB_NF:
423                 dev_dbg(pTAS2770->dev, "INV format: IBNF\n");
424                 asi_cfg_1 |= TAS2770_TDMConfigurationReg1_RXEDGE_Falling;
425                 break;
426         default:
427                 dev_err(pTAS2770->dev, "ASI format Inverse is not found\n");
428                 ret = -EINVAL;
429         }
431         snd_soc_update_bits(pTAS2770->codec, TAS2770_TDMConfigurationReg1,
432                 TAS2770_TDMConfigurationReg1_RXEDGE_Mask,
433                 asi_cfg_1);
435         switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
436         case (SND_SOC_DAIFMT_I2S):
437                 tdm_rx_start_slot = 1;
438                 break;
439         case (SND_SOC_DAIFMT_DSP_A):
440         case (SND_SOC_DAIFMT_DSP_B):
441                 tdm_rx_start_slot = 1;
442                 break;
443         case (SND_SOC_DAIFMT_LEFT_J):
444                 tdm_rx_start_slot = 0;
445                 break;
446         default:
447         dev_err(pTAS2770->dev, "DAI Format is not found, fmt=0x%x\n", fmt);
448         ret = -EINVAL;
449                 break;
450         }
452         snd_soc_update_bits(pTAS2770->codec, TAS2770_TDMConfigurationReg1,
453                 TAS2770_TDMConfigurationReg1_RXOFFSET51_Mask,
454         (tdm_rx_start_slot << TAS2770_TDMConfigurationReg1_RXOFFSET51_Shift));
456         snd_soc_update_bits(pTAS2770->codec, TAS2770_TDMConfigurationReg3,
457                 TAS2770_TDMConfigurationReg3_RXSLOTLeft30_Mask,
458                 (pTAS2770->mnLeftSlot << TAS2770_TDMConfigurationReg3_RXSLOTLeft30_Shift));
459         snd_soc_update_bits(pTAS2770->codec, TAS2770_TDMConfigurationReg3,
460                 TAS2770_TDMConfigurationReg3_RXSLOTRight74_Mask,
461         (pTAS2770->mnRightSlot << TAS2770_TDMConfigurationReg3_RXSLOTRight74_Shift));
463         value = snd_soc_read(pTAS2770->codec, TAS2770_TDMConfigurationReg3);
464         dev_dbg(pTAS2770->dev, "slot value: 0x%x", value);
466         pTAS2770->mnASIFormat = fmt;
468         return 0;
471 static int tas2770_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
473         struct snd_soc_codec *codec = dai->codec;
474         struct tas2770_priv *pTAS2770 = snd_soc_codec_get_drvdata(codec);
475         int ret = 0;
477         dev_dbg(pTAS2770->dev, "%s, format=0x%x\n", __func__, fmt);
478         mutex_lock(&pTAS2770->codec_lock);
480         ret = tas2770_set_fmt(pTAS2770, fmt);
482         mutex_unlock(&pTAS2770->codec_lock);
483         return ret;
486 static int tas2770_set_slot(struct snd_soc_codec *codec, int slot_width)
488         int ret = 0;
489         struct tas2770_priv *pTAS2770 = snd_soc_codec_get_drvdata(codec);
491         switch (slot_width) {
492         case 16:
493         ret = snd_soc_update_bits(codec,
494                 TAS2770_TDMConfigurationReg2,
495                 TAS2770_TDMConfigurationReg2_RXSLEN10_Mask,
496                 TAS2770_TDMConfigurationReg2_RXSLEN10_16Bits);
497         break;
499         case 24:
500         ret = snd_soc_update_bits(codec,
501                 TAS2770_TDMConfigurationReg2,
502                 TAS2770_TDMConfigurationReg2_RXSLEN10_Mask,
503                 TAS2770_TDMConfigurationReg2_RXSLEN10_24Bits);
504         break;
506         case 32:
507         ret = snd_soc_update_bits(codec,
508                 TAS2770_TDMConfigurationReg2,
509                 TAS2770_TDMConfigurationReg2_RXSLEN10_Mask,
510                 TAS2770_TDMConfigurationReg2_RXSLEN10_32Bits);
511         break;
513         case 0:
514         /* Do not change slot width */
515         break;
517         default:
518                 dev_dbg(pTAS2770->dev, "slot width not supported");
519                 ret = -EINVAL;
520         }
522         if (ret >= 0)
523                 pTAS2770->mnSlot_width = slot_width;
525         return ret;
528 static int tas2770_set_dai_tdm_slot(struct snd_soc_dai *dai,
529                 unsigned int tx_mask, unsigned int rx_mask,
530                 int slots, int slot_width)
532         int ret = 0;
533         struct snd_soc_codec *codec = dai->codec;
534         struct tas2770_priv *pTAS2770 = snd_soc_codec_get_drvdata(codec);
536         dev_dbg(pTAS2770->dev, "%s, tx_mask:%d, rx_mask:%d, slots:%d, slot_width:%d",
537                         __func__, tx_mask, rx_mask, slots, slot_width);
539         mutex_lock(&pTAS2770->codec_lock);
540         ret = tas2770_set_slot(codec, slot_width);
541         mutex_unlock(&pTAS2770->codec_lock);
543         return ret;
546 static struct snd_soc_dai_ops tas2770_dai_ops = {
547         .digital_mute = tas2770_mute,
548         .hw_params  = tas2770_hw_params,
549         .set_fmt    = tas2770_set_dai_fmt,
550         .set_tdm_slot = tas2770_set_dai_tdm_slot,
551 };
553 #define TAS2770_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
554                 SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
556 #define TAS2770_RATES (SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |\
557                                                 SNDRV_PCM_RATE_96000 |\
558                                                 SNDRV_PCM_RATE_192000\
559                                                 )
561 static struct snd_soc_dai_driver tas2770_dai_driver[] = {
562         {
563                 .name = "tas2770 ASI1",
564                 .id = 0,
565                 .playback = {
566                         .stream_name    = "ASI1 Playback",
567                         .channels_min   = 2,
568                         .channels_max   = 2,
569                         .rates      = TAS2770_RATES,
570                         .formats    = TAS2770_FORMATS,
571                 },
572                 .capture = {
573                         .stream_name    = "ASI1 Capture",
574                         .channels_min   = 0,
575                         .channels_max   = 2,
576                         .rates          = TAS2770_RATES,
577                         .formats    = TAS2770_FORMATS,
578                 },
579                 .ops = &tas2770_dai_ops,
580                 .symmetric_rates = 1,
581         },
582 };
584 static int tas2770_codec_probe(struct snd_soc_codec *codec)
586         struct tas2770_priv *pTAS2770 = snd_soc_codec_get_drvdata(codec);
588         dev_err(pTAS2770->dev, "%s\n", __func__);
589         pTAS2770->codec = codec;
591         return 0;
594 static int tas2770_codec_remove(struct snd_soc_codec *codec)
596         return 0;
599 static DECLARE_TLV_DB_SCALE(tas2770_digital_tlv, 1100, 50, 0);
600 static DECLARE_TLV_DB_SCALE(tas2770_playback_volume, -12750, 50, 0);
602 static const struct snd_kcontrol_new tas2770_snd_controls[] = {
603         SOC_SINGLE_TLV("Amp Output Level", TAS2770_PlaybackConfigurationReg0,
604                 0, 0x14, 0,
605                 tas2770_digital_tlv),
606         SOC_SINGLE_TLV("Playback Volume", TAS2770_PlaybackConfigurationReg2,
607                 0, TAS2770_PlaybackConfigurationReg2_VOLMAX, 1,
608                 tas2770_playback_volume),
609 };
611 static struct snd_soc_codec_driver soc_codec_driver_tas2770 = {
612         .probe                  = tas2770_codec_probe,
613         .remove                 = tas2770_codec_remove,
614         .read                   = tas2770_codec_read,
615         .write                  = tas2770_codec_write,
616         .suspend                = tas2770_codec_suspend,
617         .resume                 = tas2770_codec_resume,
618         .component_driver = {
619                 .controls               = tas2770_snd_controls,
620                 .num_controls           = ARRAY_SIZE(tas2770_snd_controls),
621                 .dapm_widgets           = tas2770_dapm_widgets,
622                 .num_dapm_widgets       = ARRAY_SIZE(tas2770_dapm_widgets),
623                 .dapm_routes            = tas2770_audio_map,
624                 .num_dapm_routes        = ARRAY_SIZE(tas2770_audio_map),
625         },
626 };
628 int tas2770_register_codec(struct tas2770_priv *pTAS2770)
630         int nResult = 0;
632         dev_info(pTAS2770->dev, "%s, enter\n", __func__);
633         nResult = snd_soc_register_codec(pTAS2770->dev,
634                 &soc_codec_driver_tas2770,
635                 tas2770_dai_driver, ARRAY_SIZE(tas2770_dai_driver));
637         return nResult;
640 int tas2770_deregister_codec(struct tas2770_priv *pTAS2770)
642         snd_soc_unregister_codec(pTAS2770->dev);
644         return 0;
647 void tas2770_LoadConfig(struct tas2770_priv *pTAS2770)
649         int ret = 0;
651         pTAS2770->hw_reset(pTAS2770);
652         snd_soc_write(pTAS2770->codec, TAS2770_SoftwareReset,
653                         TAS2770_SoftwareReset_SoftwareReset_Reset);
655         ret = tas2770_set_slot(pTAS2770->codec, pTAS2770->mnSlot_width);
656         if (ret < 0)
657                 goto end;
659         ret = tas2770_set_fmt(pTAS2770, pTAS2770->mnASIFormat);
660         if (ret < 0)
661                 goto end;
663         ret = tas2770_set_bitwidth(pTAS2770, pTAS2770->mnCh_size);
664         if (ret < 0)
665                 goto end;
667         ret = tas2770_set_samplerate(pTAS2770, pTAS2770->mnSamplingRate);
668         if (ret < 0)
669                 goto end;
671         ret = tas2770_set_power_state(pTAS2770, pTAS2770->mnPowerState);
673 end:
674 /* power up failed, restart later */
675         if (ret < 0)
676                 schedule_delayed_work(&pTAS2770->irq_work,
677                                 msecs_to_jiffies(1000));
680 MODULE_AUTHOR("Texas Instruments Inc.");
681 MODULE_DESCRIPTION("TAS2770 ALSA SOC Smart Amplifier driver");
682 MODULE_LICENSE("GPL v2");
683 #endif /* CONFIG_TAS2770_CODEC */