5ba3efe1e58909a7e4642593a530c3724d29a49b
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 Texas Instruments TAS2770 High Performance 4W Smart Amplifier
18 **
19 ** =============================================================================
20 */
22 #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
49 //#define KCONTROL_CODEC
51 #define DAPM_TO_CODEC
52 static unsigned int tas2770_codec_read(struct snd_soc_codec *codec, unsigned int reg)
53 {
54 struct tas2770_priv *pTAS2770 = snd_soc_codec_get_drvdata(codec);
55 int nResult = 0;
56 unsigned int value = 0;
58 mutex_lock(&pTAS2770->dev_lock);
60 nResult = regmap_read(pTAS2770->regmap, reg, &value);
62 if (nResult < 0)
63 dev_err(pTAS2770->dev, "%s, ERROR, reg=0x%x, E=%d\n",
64 __func__, reg, nResult);
65 else
66 dev_dbg(pTAS2770->dev, "%s, reg: 0x%x, value: 0x%x\n", __func__, reg, value);
68 mutex_unlock(&pTAS2770->dev_lock);
69 if(nResult >= 0)
70 return value;
71 else
72 return nResult;
73 }
76 static int tas2770_codec_write(struct snd_soc_codec *codec, unsigned int reg,
77 unsigned int value)
78 {
79 struct tas2770_priv *pTAS2770 = snd_soc_codec_get_drvdata(codec);
81 int nResult = 0;
83 mutex_lock(&pTAS2770->dev_lock);
85 nResult = regmap_write(pTAS2770->regmap, reg, value);
86 if(nResult < 0)
87 dev_err(pTAS2770->dev, "%s, ERROR, reg=0x%x, E=%d\n",
88 __func__, reg, nResult);
89 else
90 dev_dbg(pTAS2770->dev, "%s, reg: 0x%x, 0x%x\n", __func__, reg, value);
92 mutex_unlock(&pTAS2770->dev_lock);
94 return nResult;
96 }
99 static int tas2770_codec_suspend(struct snd_soc_codec *codec)
100 {
101 struct tas2770_priv *pTAS2770 = snd_soc_codec_get_drvdata(codec);
102 int ret = 0;
104 mutex_lock(&pTAS2770->codec_lock);
106 dev_dbg(pTAS2770->dev, "%s\n", __func__);
107 // pTAS2770->runtime_suspend(pTAS2770);
109 mutex_unlock(&pTAS2770->codec_lock);
110 return ret;
111 }
113 static int tas2770_codec_resume(struct snd_soc_codec *codec)
114 {
115 struct tas2770_priv *pTAS2770 = snd_soc_codec_get_drvdata(codec);
116 int ret = 0;
118 mutex_lock(&pTAS2770->codec_lock);
120 dev_dbg(pTAS2770->dev, "%s\n", __func__);
121 // pTAS2770->runtime_resume(pTAS2770);
123 mutex_unlock(&pTAS2770->codec_lock);
124 return ret;
125 }
127 static const struct snd_kcontrol_new tas2770_asi_controls[] = {
128 SOC_DAPM_SINGLE("Left", TAS2770_TDMConfigurationReg2,
129 4, 1, 0),
130 SOC_DAPM_SINGLE("Right", TAS2770_TDMConfigurationReg2,
131 4, 2, 0),
132 SOC_DAPM_SINGLE("LeftRightDiv2", TAS2770_TDMConfigurationReg2,
133 4, 3, 0),
134 };
137 static int tas2770_dac_event(struct snd_soc_dapm_widget *w,
138 struct snd_kcontrol *kcontrol, int event)
139 {
140 #ifdef DAPM_TO_CODEC
141 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
142 #else
143 struct snd_soc_codec *codec = w->codec;
144 #endif
145 // struct tas2770_priv *pTAS2770 = snd_soc_codec_get_drvdata(codec);
146 pr_err("%s",__func__);
147 switch (event) {
148 case SND_SOC_DAPM_POST_PMU:
149 snd_soc_update_bits(codec, TAS2770_PowerControl,
150 TAS2770_PowerControl_OperationalMode10_Mask,
151 TAS2770_PowerControl_OperationalMode10_Active);
152 break;
153 case SND_SOC_DAPM_PRE_PMD:
154 snd_soc_update_bits(codec, TAS2770_PowerControl,
155 TAS2770_PowerControl_OperationalMode10_Mask,
156 TAS2770_PowerControl_OperationalMode10_Shutdown);
157 break;
159 }
160 return 0;
162 }
164 static const struct snd_soc_dapm_widget tas2770_dapm_widgets[] = {
165 SND_SOC_DAPM_AIF_IN("ASI1", "ASI1 Playback", 0, SND_SOC_NOPM, 0, 0),
166 SND_SOC_DAPM_MIXER("ASI1 Sel",
167 TAS2770_TDMConfigurationReg2, 4, 0,
168 &tas2770_asi_controls[0],
169 ARRAY_SIZE(tas2770_asi_controls)),
170 SND_SOC_DAPM_DAC_E("DAC", NULL, SND_SOC_NOPM, 0, 0,
171 tas2770_dac_event, SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
172 SND_SOC_DAPM_OUTPUT("OUT")
174 };
176 static const struct snd_soc_dapm_route tas2770_audio_map[] = {
177 {"ASI1 Sel", "Left", "ASI1"},
178 {"ASI1 Sel", "Right", "ASI1"},
179 {"ASI1 Sel", "LeftRightDiv2", "ASI1"},
180 {"DAC", NULL, "ASI1 Sel"},
181 {"OUT", NULL, "DAC"},
182 };
185 static int tas2770_mute(struct snd_soc_dai *dai, int mute)
186 {
187 struct snd_soc_codec *codec = dai->codec;
188 struct tas2770_priv *pTAS2770 = snd_soc_codec_get_drvdata(codec);
190 dev_err(pTAS2770->dev, "%s mute %d",__func__, mute);
192 mutex_lock(&pTAS2770->codec_lock);
193 if(mute) {
194 snd_soc_update_bits(codec, TAS2770_PowerControl,
195 TAS2770_PowerControl_OperationalMode10_Mask,
196 TAS2770_PowerControl_OperationalMode10_Mute);
197 } else {
198 snd_soc_update_bits(codec, TAS2770_PowerControl,
199 TAS2770_PowerControl_OperationalMode10_Mask,
200 TAS2770_PowerControl_OperationalMode10_Active);
201 }
202 mutex_unlock(&pTAS2770->codec_lock);
203 return 0;
204 }
208 static int tas2770_hw_params(struct snd_pcm_substream *substream,
209 struct snd_pcm_hw_params *params,
210 struct snd_soc_dai *dai)
211 {
212 struct snd_soc_codec *codec = dai->codec;
213 struct tas2770_priv *pTAS2770 = snd_soc_codec_get_drvdata(codec);
214 int ret = 0;
215 dev_err(pTAS2770->dev, "%s",__func__);
216 dev_dbg(pTAS2770->dev, "%s, format: %d\n", __func__, params_format(params));
218 switch(params_format(params)) {
219 case SNDRV_PCM_FORMAT_S16_LE:
220 snd_soc_update_bits(codec,
221 TAS2770_TDMConfigurationReg2,
222 TAS2770_TDMConfigurationReg2_RXWLEN32_Mask |
223 TAS2770_TDMConfigurationReg2_RXSLEN10_Mask,
224 TAS2770_TDMConfigurationReg2_RXWLEN32_16Bits |
225 TAS2770_TDMConfigurationReg2_RXWLEN32_16Bits );
226 pTAS2770->ch_size = 16;
227 break;
228 case SNDRV_PCM_FORMAT_S24_LE:
229 snd_soc_update_bits(codec,
230 TAS2770_TDMConfigurationReg2,
231 TAS2770_TDMConfigurationReg2_RXWLEN32_Mask |
232 TAS2770_TDMConfigurationReg2_RXSLEN10_Mask,
233 TAS2770_TDMConfigurationReg2_RXWLEN32_24Bits |
234 TAS2770_TDMConfigurationReg2_RXWLEN32_24Bits );
235 pTAS2770->ch_size = 24;
236 break;
237 case SNDRV_PCM_FORMAT_S32_LE:
238 snd_soc_update_bits(codec,
239 TAS2770_TDMConfigurationReg2,
240 TAS2770_TDMConfigurationReg2_RXWLEN32_Mask |
241 TAS2770_TDMConfigurationReg2_RXSLEN10_Mask,
242 TAS2770_TDMConfigurationReg2_RXWLEN32_32Bits |
243 TAS2770_TDMConfigurationReg2_RXWLEN32_32Bits );
244 pTAS2770->ch_size = 32;
245 break;
247 }
249 dev_dbg(pTAS2770->dev, "%s, sample rate: %d\n", __func__, params_rate(params));
250 switch(params_rate(params))
251 {
252 case 48000:
253 snd_soc_update_bits(codec,
254 TAS2770_TDMConfigurationReg0,
255 TAS2770_TDMConfigurationReg0_SAMPRATERAMP_Mask,
256 TAS2770_TDMConfigurationReg0_SAMPRATERAMP_48KHz);
257 snd_soc_update_bits(codec,
258 TAS2770_TDMConfigurationReg0,
259 TAS2770_TDMConfigurationReg0_SAMPRATE31_Mask,
260 TAS2770_TDMConfigurationReg0_SAMPRATE31_44_1_48kHz);
261 break;
262 case 44100:
263 snd_soc_update_bits(codec,
264 TAS2770_TDMConfigurationReg0,
265 TAS2770_TDMConfigurationReg0_SAMPRATERAMP_Mask,
266 TAS2770_TDMConfigurationReg0_SAMPRATERAMP_44_1KHz);
267 snd_soc_update_bits(codec,
268 TAS2770_TDMConfigurationReg0,
269 TAS2770_TDMConfigurationReg0_SAMPRATE31_Mask,
270 TAS2770_TDMConfigurationReg0_SAMPRATE31_44_1_48kHz);
271 break;
272 case 96000:
273 snd_soc_update_bits(codec,
274 TAS2770_TDMConfigurationReg0,
275 TAS2770_TDMConfigurationReg0_SAMPRATERAMP_Mask,
276 TAS2770_TDMConfigurationReg0_SAMPRATERAMP_48KHz);
277 snd_soc_update_bits(codec,
278 TAS2770_TDMConfigurationReg0,
279 TAS2770_TDMConfigurationReg0_SAMPRATE31_Mask,
280 TAS2770_TDMConfigurationReg0_SAMPRATE31_88_2_96kHz);
281 break;
282 case 88200:
283 snd_soc_update_bits(codec,
284 TAS2770_TDMConfigurationReg0,
285 TAS2770_TDMConfigurationReg0_SAMPRATERAMP_Mask,
286 TAS2770_TDMConfigurationReg0_SAMPRATERAMP_44_1KHz);
287 snd_soc_update_bits(codec,
288 TAS2770_TDMConfigurationReg0,
289 TAS2770_TDMConfigurationReg0_SAMPRATE31_Mask,
290 TAS2770_TDMConfigurationReg0_SAMPRATE31_88_2_96kHz);
291 break;
292 case 19200:
293 snd_soc_update_bits(codec,
294 TAS2770_TDMConfigurationReg0,
295 TAS2770_TDMConfigurationReg0_SAMPRATERAMP_Mask,
296 TAS2770_TDMConfigurationReg0_SAMPRATERAMP_48KHz);
297 snd_soc_update_bits(codec,
298 TAS2770_TDMConfigurationReg0,
299 TAS2770_TDMConfigurationReg0_SAMPRATE31_Mask,
300 TAS2770_TDMConfigurationReg0_SAMPRATE31_176_4_192kHz);
301 break;
302 case 17640:
303 snd_soc_update_bits(codec,
304 TAS2770_TDMConfigurationReg0,
305 TAS2770_TDMConfigurationReg0_SAMPRATERAMP_Mask,
306 TAS2770_TDMConfigurationReg0_SAMPRATERAMP_44_1KHz);
307 snd_soc_update_bits(codec,
308 TAS2770_TDMConfigurationReg0,
309 TAS2770_TDMConfigurationReg0_SAMPRATE31_Mask,
310 TAS2770_TDMConfigurationReg0_SAMPRATE31_176_4_192kHz);
311 break;
312 default:
313 dev_dbg(pTAS2770->dev, "%s, unsupported sample rate\n", __func__);
315 }
316 return ret;
317 }
319 static int tas2770_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
320 {
321 u8 tdm_rx_start_slot = 0, asi_cfg_1 = 0;
322 struct snd_soc_codec *codec = dai->codec;
323 struct tas2770_priv *pTAS2770 = snd_soc_codec_get_drvdata(codec);
324 int ret = 0;
326 dev_dbg(pTAS2770->dev, "%s, format=0x%x\n", __func__, fmt);
328 #if 1
329 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
330 case SND_SOC_DAIFMT_CBS_CFS:
331 asi_cfg_1 = 0x00;
332 break;
333 default:
334 dev_err(pTAS2770->dev, "ASI format master is not found\n");
335 ret = -EINVAL;
336 }
338 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
339 case SND_SOC_DAIFMT_NB_NF:
340 dev_dbg(pTAS2770->dev, "INV format: NBNF\n");
341 asi_cfg_1 |= TAS2770_TDMConfigurationReg1_RXEDGE_Rising;
342 break;
343 case SND_SOC_DAIFMT_IB_NF:
344 dev_dbg(pTAS2770->dev, "INV format: IBNF\n");
345 asi_cfg_1 |= TAS2770_TDMConfigurationReg1_RXEDGE_Falling;
346 break;
347 default:
348 dev_err(pTAS2770->dev, "ASI format Inverse is not found\n");
349 ret = -EINVAL;
350 }
352 snd_soc_update_bits(codec, TAS2770_TDMConfigurationReg1,
353 TAS2770_TDMConfigurationReg1_RXEDGE_Mask,
354 asi_cfg_1);
356 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
357 case (SND_SOC_DAIFMT_I2S):
358 tdm_rx_start_slot = 1;
359 break;
360 case (SND_SOC_DAIFMT_DSP_A):
361 case (SND_SOC_DAIFMT_DSP_B):
362 tdm_rx_start_slot = 1;
363 break;
364 case (SND_SOC_DAIFMT_LEFT_J):
365 tdm_rx_start_slot = 0;
366 break;
367 default:
368 dev_err(pTAS2770->dev, "DAI Format is not found, fmt=0x%x\n", fmt);
369 ret = -EINVAL;
370 break;
371 }
373 snd_soc_update_bits(codec, TAS2770_TDMConfigurationReg1,
374 TAS2770_TDMConfigurationReg1_RXOFFSET51_Mask,
375 (tdm_rx_start_slot << TAS2770_TDMConfigurationReg1_RXOFFSET51_Shift));
376 #endif
377 return ret;
378 }
380 static struct snd_soc_dai_ops tas2770_dai_ops = {
381 .digital_mute = tas2770_mute,
382 .hw_params = tas2770_hw_params,
383 .set_fmt = tas2770_set_dai_fmt,
384 };
386 #define TAS2770_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
387 SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
389 #define TAS2770_RATES (SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 \
390 SNDRV_PCM_RATE_88200 |\
391 SNDRV_PCM_RATE_96000 |\
392 SNDRV_PCM_RATE_176400 |\
393 SNDRV_PCM_RATE_192000\
394 )
396 static struct snd_soc_dai_driver tas2770_dai_driver[] = {
397 {
398 .name = "tas2770 ASI1",
399 .id = 0,
400 .playback = {
401 .stream_name = "ASI1 Playback",
402 .channels_min = 2,
403 .channels_max = 2,
404 .rates = SNDRV_PCM_RATE_8000_192000,
405 .formats = TAS2770_FORMATS,
406 },
407 .capture = {
408 .stream_name = "ASI1 Capture",
409 .channels_min = 0,
410 .channels_max = 2,
411 .rates = SNDRV_PCM_RATE_8000_192000,
412 .formats = TAS2770_FORMATS,
413 },
414 .ops = &tas2770_dai_ops,
415 .symmetric_rates = 1,
416 },
417 };
419 static int tas2770_codec_probe(struct snd_soc_codec *codec)
420 {
421 struct tas2770_priv *pTAS2770 = snd_soc_codec_get_drvdata(codec);
423 dev_err(pTAS2770->dev, "%s\n", __func__);
425 return 0;
426 }
428 static int tas2770_codec_remove(struct snd_soc_codec *codec)
429 {
430 return 0;
431 }
433 #if 0
435 /*
436 * DAC digital volumes. From 0 to 31 dB in 1 dB steps
437 */
438 static DECLARE_TLV_DB_SCALE(dac_tlv, 0, 100, 0);
440 static const struct snd_kcontrol_new tas2770_snd_controls[] = {
441 SOC_SINGLE_TLV("DAC Playback Volume", TAS2770_PlaybackConfigurationReg0, 0, 0x1f, 0,
442 dac_tlv),
443 // SOC_SINGLE_EXT("TAS2770 PowerCtrl", SND_SOC_NOPM, 0, 0x0001, 0,
444 // tas2770_power_ctrl_get, tas2770_power_ctrl_put),
445 };
446 #endif
448 static struct snd_soc_codec_driver soc_codec_driver_tas2770 = {
449 .probe = tas2770_codec_probe,
450 .remove = tas2770_codec_remove,
451 .read = tas2770_codec_read,
452 .write = tas2770_codec_write,
453 .suspend = tas2770_codec_suspend,
454 .resume = tas2770_codec_resume,
455 .component_driver = {
456 // .controls = tas2770_snd_controls,
457 // .num_controls = ARRAY_SIZE(tas2770_snd_controls),
458 .dapm_widgets = tas2770_dapm_widgets,
459 .num_dapm_widgets = ARRAY_SIZE(tas2770_dapm_widgets),
460 .dapm_routes = tas2770_audio_map,
461 .num_dapm_routes = ARRAY_SIZE(tas2770_audio_map),
462 },
463 };
465 int tas2770_register_codec(struct tas2770_priv *pTAS2770)
466 {
467 int nResult = 0;
469 dev_info(pTAS2770->dev, "%s, enter\n", __func__);
470 nResult = snd_soc_register_codec(pTAS2770->dev,
471 &soc_codec_driver_tas2770,
472 tas2770_dai_driver, ARRAY_SIZE(tas2770_dai_driver));
473 dev_info(pTAS2770->dev, "%s, enter result %d\n", __func__,nResult);
474 return nResult;
475 }
477 int tas2770_deregister_codec(struct tas2770_priv *pTAS2770)
478 {
479 snd_soc_unregister_codec(pTAS2770->dev);
481 return 0;
482 }
484 MODULE_AUTHOR("Texas Instruments Inc.");
485 MODULE_DESCRIPTION("TAS2770 ALSA SOC Smart Amplifier driver");
486 MODULE_LICENSE("GPL v2");
487 #endif /* CONFIG_TAS2770_CODEC */