5e34d07ac7c76924f2753d9509db972e2ef78872
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;
100 }
103 static int tas2770_codec_suspend(struct snd_soc_codec *codec)
104 {
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;
114 }
116 static int tas2770_codec_resume(struct snd_soc_codec *codec)
117 {
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;
127 }
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)
141 {
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;
170 }
172 static int tas2770_dac_event(struct snd_soc_dapm_widget *w,
173 struct snd_kcontrol *kcontrol, int event)
174 {
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;
192 }
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)
227 {
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;
240 }
242 static int tas2770_set_bitwidth(struct tas2770_priv *pTAS2770, int bitwidth)
243 {
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;
293 }
295 static int tas2770_set_samplerate(struct tas2770_priv *pTAS2770, int samplerate)
296 {
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;
365 }
367 static int tas2770_hw_params(struct snd_pcm_substream *substream,
368 struct snd_pcm_hw_params *params,
369 struct snd_soc_dai *dai)
370 {
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;
391 }
393 static int tas2770_set_fmt(struct tas2770_priv *pTAS2770, unsigned int fmt)
394 {
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;
460 }
462 static int tas2770_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
463 {
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;
475 }
477 static int tas2770_set_slot(struct snd_soc_codec *codec, int slot_width)
478 {
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;
517 }
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)
522 {
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;
535 }
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)
576 {
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;
583 }
585 static int tas2770_codec_remove(struct snd_soc_codec *codec)
586 {
587 return 0;
588 }
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)
620 {
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;
629 }
631 int tas2770_deregister_codec(struct tas2770_priv *pTAS2770)
632 {
633 snd_soc_unregister_codec(pTAS2770->dev);
635 return 0;
636 }
638 void tas2770_LoadConfig(struct tas2770_priv *pTAS2770)
639 {
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));
669 }
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 */