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 ** tas2562-codec.c
15 **
16 ** Description:
17 ** ALSA SoC driver for Texas Instruments TAS2562 High Performance 4W Smart
18 ** Amplifier
19 **
20 ** =============================================================================
21 */
23 #ifdef CONFIG_TAS2562_CODEC
24 #define DEBUG 5
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 "tas2562.h"
48 #define TAS2562_MDELAY 0xFFFFFFFE
49 /* #define KCONTROL_CODEC */
51 static char pICN[] = {0x00, 0x03, 0x46, 0xdc};
52 static char const *iv_enable_text[] = {"Off", "On"};
53 static int tas2562iv_enable;
54 static const struct soc_enum tas2562_enum[] = {
55 SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(iv_enable_text), iv_enable_text),
56 };
57 static int tas2562_set_fmt(struct tas2562_priv *pTAS2562, unsigned int fmt);
59 static unsigned int tas2562_codec_read(struct snd_soc_codec *codec,
60 unsigned int reg)
61 {
62 struct tas2562_priv *pTAS2562 = snd_soc_codec_get_drvdata(codec);
63 int nResult = 0;
64 unsigned int value = 0;
66 mutex_lock(&pTAS2562->dev_lock);
68 nResult = regmap_read(pTAS2562->regmap, reg, &value);
70 if (nResult < 0)
71 dev_err(pTAS2562->dev, "%s, ERROR, reg=0x%x, E=%d\n",
72 __func__, reg, nResult);
73 else
74 dev_dbg(pTAS2562->dev, "%s, reg: 0x%x, value: 0x%x\n",
75 __func__, reg, value);
77 mutex_unlock(&pTAS2562->dev_lock);
79 if (nResult >= 0)
80 return value;
81 else
82 return nResult;
83 }
85 static int tas2562_iv_enable(struct tas2562_priv *pTAS2562, int enable)
86 {
87 int nResult;
89 if (enable) {
90 pr_debug("%s: tas2562iv_enable \n", __func__);
91 nResult = pTAS2562->update_bits(pTAS2562, TAS2562_PowerControl,
92 TAS2562_PowerControl_ISNSPower_Mask |
93 TAS2562_PowerControl_VSNSPower_Mask,
94 TAS2562_PowerControl_VSNSPower_Active |
95 TAS2562_PowerControl_ISNSPower_Active);
96 } else {
97 pr_debug("%s: tas2562iv_disable \n", __func__);
98 nResult = pTAS2562->update_bits(pTAS2562, TAS2562_PowerControl,
99 TAS2562_PowerControl_ISNSPower_Mask |
100 TAS2562_PowerControl_VSNSPower_Mask,
101 TAS2562_PowerControl_VSNSPower_PoweredDown |
102 TAS2562_PowerControl_ISNSPower_PoweredDown);
103 }
104 tas2562iv_enable = enable;
106 return nResult;
107 }
109 static int tas2562iv_put(struct snd_kcontrol *kcontrol,
110 struct snd_ctl_elem_value *ucontrol)
111 {
112 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
113 struct tas2562_priv *pTAS2562 = snd_soc_codec_get_drvdata(codec);
114 int iv_enable = 0, nResult = 0;
116 if (codec == NULL) {
117 pr_err("%s: codec is NULL \n", __func__);
118 return 0;
119 }
121 iv_enable = ucontrol->value.integer.value[0];
123 nResult = tas2562_iv_enable(pTAS2562, iv_enable);
125 pr_debug("%s: tas2562iv_enable = %d\n", __func__, tas2562iv_enable);
127 return nResult;
128 }
130 static int tas2562iv_get(struct snd_kcontrol *kcontrol,
131 struct snd_ctl_elem_value *ucontrol)
132 {
133 ucontrol->value.integer.value[0] = tas2562iv_enable;
134 return 0;
135 }
137 static const struct snd_kcontrol_new tas2562_controls[] = {
138 SOC_ENUM_EXT("TAS2562 IVSENSE ENABLE", tas2562_enum[0],
139 tas2562iv_get, tas2562iv_put),
140 };
142 static int tas2562_codec_write(struct snd_soc_codec *codec, unsigned int reg,
143 unsigned int value)
144 {
145 struct tas2562_priv *pTAS2562 = snd_soc_codec_get_drvdata(codec);
147 int nResult = 0;
149 mutex_lock(&pTAS2562->dev_lock);
151 nResult = regmap_write(pTAS2562->regmap, reg, value);
152 if (nResult < 0)
153 dev_err(pTAS2562->dev, "%s, ERROR, reg=0x%x, E=%d\n",
154 __func__, reg, nResult);
155 else
156 dev_dbg(pTAS2562->dev, "%s, reg: 0x%x, 0x%x\n",
157 __func__, reg, value);
159 mutex_unlock(&pTAS2562->dev_lock);
161 return nResult;
163 }
166 static int tas2562_codec_suspend(struct snd_soc_codec *codec)
167 {
168 struct tas2562_priv *pTAS2562 = snd_soc_codec_get_drvdata(codec);
169 int ret = 0;
171 mutex_lock(&pTAS2562->codec_lock);
173 dev_dbg(pTAS2562->dev, "%s\n", __func__);
174 pTAS2562->runtime_suspend(pTAS2562);
176 mutex_unlock(&pTAS2562->codec_lock);
177 return ret;
178 }
180 static int tas2562_codec_resume(struct snd_soc_codec *codec)
181 {
182 struct tas2562_priv *pTAS2562 = snd_soc_codec_get_drvdata(codec);
183 int ret = 0;
185 mutex_lock(&pTAS2562->codec_lock);
187 dev_dbg(pTAS2562->dev, "%s\n", __func__);
188 pTAS2562->runtime_resume(pTAS2562);
190 mutex_unlock(&pTAS2562->codec_lock);
191 return ret;
192 }
194 static const struct snd_kcontrol_new tas2562_asi_controls[] = {
195 SOC_DAPM_SINGLE("Left", TAS2562_TDMConfigurationReg2,
196 4, 1, 0),
197 SOC_DAPM_SINGLE("Right", TAS2562_TDMConfigurationReg2,
198 4, 2, 0),
199 SOC_DAPM_SINGLE("LeftRightDiv2", TAS2562_TDMConfigurationReg2,
200 4, 3, 0),
201 };
203 static int tas2562_set_power_state(struct tas2562_priv *pTAS2562, int state)
204 {
205 int nResult = 0;
206 /*unsigned int nValue;*/
208 dev_err(pTAS2562->dev, "set power state: %d\n", state);
210 switch (state) {
211 case TAS2562_POWER_ACTIVE:
212 //if set format was not called by asoc, then set it default
213 if(pTAS2562->mnASIFormat == 0)
214 pTAS2562->mnASIFormat = SND_SOC_DAIFMT_CBS_CFS
215 | SND_SOC_DAIFMT_IB_NF
216 | SND_SOC_DAIFMT_I2S;
217 nResult = tas2562_set_fmt(pTAS2562, pTAS2562->mnASIFormat);
218 if (nResult < 0)
219 return nResult;
221 nResult = pTAS2562->update_bits(pTAS2562, TAS2562_PowerControl,
222 TAS2562_PowerControl_OperationalMode10_Mask,
223 TAS2562_PowerControl_OperationalMode10_Active);
224 if (nResult < 0)
225 return nResult;
226 pTAS2562->mbPowerUp = true;
227 dev_info(pTAS2562->dev, "set ICN to -80dB\n");
228 nResult = pTAS2562->bulk_write(pTAS2562, TAS2562_ICN_REG, pICN, 4);
229 pTAS2562->mnPowerState = TAS2562_POWER_ACTIVE;
230 pTAS2562->enableIRQ(pTAS2562, true);
231 break;
233 case TAS2562_POWER_MUTE:
234 nResult = pTAS2562->update_bits(pTAS2562, TAS2562_PowerControl,
235 TAS2562_PowerControl_OperationalMode10_Mask |
236 TAS2562_PowerControl_ISNSPower_Mask |
237 TAS2562_PowerControl_VSNSPower_Mask,
238 TAS2562_PowerControl_OperationalMode10_Mute |
239 TAS2562_PowerControl_VSNSPower_Active |
240 TAS2562_PowerControl_ISNSPower_Active);
241 pTAS2562->mbPowerUp = true;
242 pTAS2562->mnPowerState = TAS2562_POWER_MUTE;
243 break;
245 case TAS2562_POWER_SHUTDOWN:
246 pTAS2562->enableIRQ(pTAS2562, false);
247 if (hrtimer_active(&pTAS2562->mtimer))
248 {
249 dev_info(pTAS2562->dev, "cancel timer\n");
250 hrtimer_cancel(&pTAS2562->mtimer);
251 }
253 nResult = pTAS2562->update_bits(pTAS2562, TAS2562_PowerControl,
254 TAS2562_PowerControl_OperationalMode10_Mask,
255 TAS2562_PowerControl_OperationalMode10_Shutdown);
256 pTAS2562->mbPowerUp = false;
257 pTAS2562->mnPowerState = TAS2562_POWER_SHUTDOWN;
258 msleep(20);
260 break;
262 default:
263 dev_err(pTAS2562->dev, "wrong power state setting %d\n", state);
265 }
267 return nResult;
268 }
271 static int tas2562_dac_event(struct snd_soc_dapm_widget *w,
272 struct snd_kcontrol *kcontrol, int event)
273 {
274 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
275 struct tas2562_priv *pTAS2562 = snd_soc_codec_get_drvdata(codec);
277 switch (event) {
278 case SND_SOC_DAPM_POST_PMU:
279 tas2562_set_power_state(pTAS2562, TAS2562_POWER_ACTIVE);
280 break;
281 case SND_SOC_DAPM_PRE_PMD:
282 tas2562_set_power_state(pTAS2562, TAS2562_POWER_SHUTDOWN);
283 break;
285 }
286 return 0;
288 }
290 static const struct snd_soc_dapm_widget tas2562_dapm_widgets[] = {
291 SND_SOC_DAPM_AIF_IN("ASI1", "ASI1 Playback", 0, SND_SOC_NOPM, 0, 0),
292 SND_SOC_DAPM_AIF_OUT("Voltage Sense", "ASI1 Capture", 1, TAS2562_PowerControl, 2, 1),
293 SND_SOC_DAPM_AIF_OUT("Current Sense", "ASI1 Capture", 0, TAS2562_PowerControl, 3, 1),
294 SND_SOC_DAPM_MIXER("ASI1 Sel",
295 TAS2562_TDMConfigurationReg2, 4, 0,
296 &tas2562_asi_controls[0],
297 ARRAY_SIZE(tas2562_asi_controls)),
298 SND_SOC_DAPM_DAC_E("DAC", NULL, SND_SOC_NOPM, 0, 0, tas2562_dac_event,
299 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
300 SND_SOC_DAPM_OUTPUT("OUT"),
301 SND_SOC_DAPM_SIGGEN("VMON"),
302 SND_SOC_DAPM_SIGGEN("IMON")
303 };
305 static const struct snd_soc_dapm_route tas2562_audio_map[] = {
306 {"ASI1 Sel", "Left", "ASI1"},
307 {"ASI1 Sel", "Right", "ASI1"},
308 {"ASI1 Sel", "LeftRightDiv2", "ASI1"},
309 {"DAC", NULL, "ASI1 Sel"},
310 {"OUT", NULL, "DAC"},
311 /*{"VMON", NULL, "Voltage Sense"},
312 {"IMON", NULL, "Current Sense"},*/
313 {"Voltage Sense", NULL, "VMON"},
314 {"Current Sense", NULL, "IMON"},
315 };
318 static int tas2562_mute(struct snd_soc_dai *dai, int mute)
319 {
320 struct snd_soc_codec *codec = dai->codec;
321 struct tas2562_priv *pTAS2562 = snd_soc_codec_get_drvdata(codec);
323 dev_dbg(pTAS2562->dev, "%s, %d \n", __func__, mute);
325 mutex_lock(&pTAS2562->codec_lock);
326 if (mute) {
327 tas2562_set_power_state(pTAS2562, TAS2562_POWER_SHUTDOWN);
328 } else {
329 tas2562_set_power_state(pTAS2562, TAS2562_POWER_ACTIVE);
330 }
331 mutex_unlock(&pTAS2562->codec_lock);
332 return 0;
333 }
335 static int tas2562_slot_config(struct snd_soc_codec *codec, struct tas2562_priv *pTAS2562, int blr_clk_ratio)
336 {
337 int ret = 0;
338 pTAS2562->update_bits(pTAS2562,
339 TAS2562_TDMConfigurationReg5, 0xff, 0x42);
341 pTAS2562->update_bits(pTAS2562,
342 TAS2562_TDMConfigurationReg6, 0xff, 0x40);
344 return ret;
345 }
347 static int tas2562_set_slot(struct snd_soc_codec *codec, int slot_width)
348 {
349 int ret = 0;
350 struct tas2562_priv *pTAS2562 = snd_soc_codec_get_drvdata(codec);
352 switch (slot_width) {
353 case 16:
354 ret = pTAS2562->update_bits(pTAS2562,
355 TAS2562_TDMConfigurationReg2,
356 TAS2562_TDMConfigurationReg2_RXSLEN10_Mask,
357 TAS2562_TDMConfigurationReg2_RXSLEN10_16Bits);
358 break;
360 case 24:
361 ret = pTAS2562->update_bits(pTAS2562,
362 TAS2562_TDMConfigurationReg2,
363 TAS2562_TDMConfigurationReg2_RXSLEN10_Mask,
364 TAS2562_TDMConfigurationReg2_RXSLEN10_24Bits);
365 break;
367 case 32:
368 ret = pTAS2562->update_bits(pTAS2562,
369 TAS2562_TDMConfigurationReg2,
370 TAS2562_TDMConfigurationReg2_RXSLEN10_Mask,
371 TAS2562_TDMConfigurationReg2_RXSLEN10_32Bits);
372 break;
374 case 0:
375 /* Do not change slot width */
376 break;
378 default:
379 dev_err(pTAS2562->dev, "slot width not supported");
380 ret = -EINVAL;
381 }
383 if (ret >= 0)
384 pTAS2562->mnSlot_width = slot_width;
386 return ret;
387 }
389 static int tas2562_set_bitwidth(struct tas2562_priv *pTAS2562, int bitwidth)
390 {
391 int slot_width_tmp = 16;
392 dev_info(pTAS2562->dev, "%s %d\n", __func__, bitwidth);
394 switch (bitwidth) {
395 case SNDRV_PCM_FORMAT_S16_LE:
396 pTAS2562->update_bits(pTAS2562,
397 TAS2562_TDMConfigurationReg2,
398 TAS2562_TDMConfigurationReg2_RXWLEN32_Mask,
399 TAS2562_TDMConfigurationReg2_RXWLEN32_16Bits);
400 pTAS2562->mnCh_size = 16;
401 if (pTAS2562->mnSlot_width == 0)
402 slot_width_tmp = 16;
403 break;
404 case SNDRV_PCM_FORMAT_S24_LE:
405 pTAS2562->update_bits(pTAS2562,
406 TAS2562_TDMConfigurationReg2,
407 TAS2562_TDMConfigurationReg2_RXWLEN32_Mask,
408 TAS2562_TDMConfigurationReg2_RXWLEN32_24Bits);
409 pTAS2562->mnCh_size = 24;
410 if (pTAS2562->mnSlot_width == 0)
411 slot_width_tmp = 32;
412 break;
413 case SNDRV_PCM_FORMAT_S32_LE:
414 pTAS2562->update_bits(pTAS2562,
415 TAS2562_TDMConfigurationReg2,
416 TAS2562_TDMConfigurationReg2_RXWLEN32_Mask,
417 TAS2562_TDMConfigurationReg2_RXWLEN32_32Bits);
418 pTAS2562->mnCh_size = 32;
419 if (pTAS2562->mnSlot_width == 0)
420 slot_width_tmp = 32;
421 break;
423 default:
424 dev_info(pTAS2562->dev, "Not supported params format\n");
425 }
427 /* If machine driver did not call set slot width */
428 if (pTAS2562->mnSlot_width == 0)
429 tas2562_set_slot(pTAS2562->codec, slot_width_tmp);
431 dev_info(pTAS2562->dev, "mnCh_size: %d\n", pTAS2562->mnCh_size);
432 pTAS2562->mnPCMFormat = bitwidth;
434 return 0;
435 }
437 static int tas2562_set_samplerate(struct tas2562_priv *pTAS2562, int samplerate)
438 {
439 switch (samplerate) {
440 case 48000:
441 pTAS2562->update_bits(pTAS2562,
442 TAS2562_TDMConfigurationReg0,
443 TAS2562_TDMConfigurationReg0_SAMPRATERAMP_Mask,
444 TAS2562_TDMConfigurationReg0_SAMPRATERAMP_48KHz);
445 pTAS2562->update_bits(pTAS2562,
446 TAS2562_TDMConfigurationReg0,
447 TAS2562_TDMConfigurationReg0_SAMPRATE31_Mask,
448 TAS2562_TDMConfigurationReg0_SAMPRATE31_44_1_48kHz);
449 break;
450 case 44100:
451 pTAS2562->update_bits(pTAS2562,
452 TAS2562_TDMConfigurationReg0,
453 TAS2562_TDMConfigurationReg0_SAMPRATERAMP_Mask,
454 TAS2562_TDMConfigurationReg0_SAMPRATERAMP_44_1KHz);
455 pTAS2562->update_bits(pTAS2562,
456 TAS2562_TDMConfigurationReg0,
457 TAS2562_TDMConfigurationReg0_SAMPRATE31_Mask,
458 TAS2562_TDMConfigurationReg0_SAMPRATE31_44_1_48kHz);
459 break;
460 case 96000:
461 pTAS2562->update_bits(pTAS2562,
462 TAS2562_TDMConfigurationReg0,
463 TAS2562_TDMConfigurationReg0_SAMPRATERAMP_Mask,
464 TAS2562_TDMConfigurationReg0_SAMPRATERAMP_48KHz);
465 pTAS2562->update_bits(pTAS2562,
466 TAS2562_TDMConfigurationReg0,
467 TAS2562_TDMConfigurationReg0_SAMPRATE31_Mask,
468 TAS2562_TDMConfigurationReg0_SAMPRATE31_88_2_96kHz);
469 break;
470 case 88200:
471 pTAS2562->update_bits(pTAS2562,
472 TAS2562_TDMConfigurationReg0,
473 TAS2562_TDMConfigurationReg0_SAMPRATERAMP_Mask,
474 TAS2562_TDMConfigurationReg0_SAMPRATERAMP_44_1KHz);
475 pTAS2562->update_bits(pTAS2562,
476 TAS2562_TDMConfigurationReg0,
477 TAS2562_TDMConfigurationReg0_SAMPRATE31_Mask,
478 TAS2562_TDMConfigurationReg0_SAMPRATE31_88_2_96kHz);
479 break;
480 case 19200:
481 pTAS2562->update_bits(pTAS2562,
482 TAS2562_TDMConfigurationReg0,
483 TAS2562_TDMConfigurationReg0_SAMPRATERAMP_Mask,
484 TAS2562_TDMConfigurationReg0_SAMPRATERAMP_48KHz);
485 pTAS2562->update_bits(pTAS2562,
486 TAS2562_TDMConfigurationReg0,
487 TAS2562_TDMConfigurationReg0_SAMPRATE31_Mask,
488 TAS2562_TDMConfigurationReg0_SAMPRATE31_176_4_192kHz);
489 break;
490 case 17640:
491 pTAS2562->update_bits(pTAS2562,
492 TAS2562_TDMConfigurationReg0,
493 TAS2562_TDMConfigurationReg0_SAMPRATERAMP_Mask,
494 TAS2562_TDMConfigurationReg0_SAMPRATERAMP_44_1KHz);
495 pTAS2562->update_bits(pTAS2562,
496 TAS2562_TDMConfigurationReg0,
497 TAS2562_TDMConfigurationReg0_SAMPRATE31_Mask,
498 TAS2562_TDMConfigurationReg0_SAMPRATE31_176_4_192kHz);
499 break;
500 default:
501 dev_info(pTAS2562->dev, "%s, unsupported sample rate, %d\n", __func__, samplerate);
503 }
505 pTAS2562->mnSamplingRate = samplerate;
506 return 0;
507 }
511 static int tas2562_hw_params(struct snd_pcm_substream *substream,
512 struct snd_pcm_hw_params *params,
513 struct snd_soc_dai *dai)
514 {
515 struct snd_soc_codec *codec = dai->codec;
516 struct tas2562_priv *pTAS2562 = snd_soc_codec_get_drvdata(codec);
517 int blr_clk_ratio;
518 int ret = 0;
520 dev_dbg(pTAS2562->dev, "%s, format: %d\n", __func__,
521 params_format(params));
523 mutex_lock(&pTAS2562->codec_lock);
525 ret = tas2562_set_bitwidth(pTAS2562, params_format(params));
526 if(ret < 0)
527 {
528 dev_info(pTAS2562->dev, "set bitwidth failed, %d\n", ret);
529 goto ret;
530 }
532 blr_clk_ratio = params_channels(params) * pTAS2562->mnCh_size;
533 dev_info(pTAS2562->dev, "blr_clk_ratio: %d\n", blr_clk_ratio);
534 if(blr_clk_ratio != 0)
535 tas2562_slot_config(pTAS2562->codec, pTAS2562, blr_clk_ratio);
537 dev_info(pTAS2562->dev, "%s, sample rate: %d\n", __func__,
538 params_rate(params));
540 ret = tas2562_set_samplerate(pTAS2562, params_rate(params));
542 ret:
543 mutex_unlock(&pTAS2562->codec_lock);
544 return ret;
545 }
547 static int tas2562_set_fmt(struct tas2562_priv *pTAS2562, unsigned int fmt)
548 {
549 u8 tdm_rx_start_slot = 0, asi_cfg_1 = 0;
550 int ret = 0;
552 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
553 case SND_SOC_DAIFMT_CBS_CFS:
554 asi_cfg_1 = 0x00;
555 break;
556 default:
557 dev_err(pTAS2562->dev, "ASI format master is not found\n");
558 ret = -EINVAL;
559 }
561 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
562 case SND_SOC_DAIFMT_NB_NF:
563 dev_info(pTAS2562->dev, "INV format: NBNF\n");
564 asi_cfg_1 |= TAS2562_TDMConfigurationReg1_RXEDGE_Rising;
565 break;
566 case SND_SOC_DAIFMT_IB_NF:
567 dev_info(pTAS2562->dev, "INV format: IBNF\n");
568 asi_cfg_1 |= TAS2562_TDMConfigurationReg1_RXEDGE_Falling;
569 break;
570 default:
571 dev_err(pTAS2562->dev, "ASI format Inverse is not found\n");
572 ret = -EINVAL;
573 }
575 pTAS2562->update_bits(pTAS2562, TAS2562_TDMConfigurationReg1,
576 TAS2562_TDMConfigurationReg1_RXEDGE_Mask,
577 asi_cfg_1);
579 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
580 case (SND_SOC_DAIFMT_I2S):
581 tdm_rx_start_slot = 1;
582 break;
583 case (SND_SOC_DAIFMT_DSP_A):
584 case (SND_SOC_DAIFMT_DSP_B):
585 tdm_rx_start_slot = 1;
586 break;
587 case (SND_SOC_DAIFMT_LEFT_J):
588 tdm_rx_start_slot = 0;
589 break;
590 default:
591 dev_err(pTAS2562->dev, "DAI Format is not found, fmt=0x%x\n", fmt);
592 ret = -EINVAL;
593 break;
594 }
596 pTAS2562->update_bits(pTAS2562, TAS2562_TDMConfigurationReg1,
597 TAS2562_TDMConfigurationReg1_RXOFFSET51_Mask,
598 (tdm_rx_start_slot << TAS2562_TDMConfigurationReg1_RXOFFSET51_Shift));
600 pTAS2562->mnASIFormat = fmt;
602 return 0;
603 }
605 static int tas2562_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
606 {
607 struct snd_soc_codec *codec = dai->codec;
608 struct tas2562_priv *pTAS2562 = snd_soc_codec_get_drvdata(codec);
609 int ret = 0;
611 dev_dbg(pTAS2562->dev, "%s, format=0x%x\n", __func__, fmt);
613 ret = tas2562_set_fmt(pTAS2562, fmt);
614 return ret;
615 }
617 static int tas2562_set_dai_tdm_slot(struct snd_soc_dai *dai,
618 unsigned int tx_mask, unsigned int rx_mask,
619 int slots, int slot_width)
620 {
621 int ret = 0;
622 struct snd_soc_codec *codec = dai->codec;
623 struct tas2562_priv *pTAS2562 = snd_soc_codec_get_drvdata(codec);
625 dev_dbg(pTAS2562->dev, "%s, tx_mask:%d, rx_mask:%d, slots:%d, slot_width:%d",
626 __func__, tx_mask, rx_mask, slots, slot_width);
628 ret = tas2562_set_slot(codec, slot_width);
630 return ret;
631 }
633 static struct snd_soc_dai_ops tas2562_dai_ops = {
634 .digital_mute = tas2562_mute,
635 .hw_params = tas2562_hw_params,
636 .set_fmt = tas2562_set_dai_fmt,
637 .set_tdm_slot = tas2562_set_dai_tdm_slot,
638 };
640 #define TAS2562_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
641 SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
643 #define TAS2562_RATES (SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 \
644 SNDRV_PCM_RATE_88200 |\
645 SNDRV_PCM_RATE_96000 |\
646 SNDRV_PCM_RATE_176400 |\
647 SNDRV_PCM_RATE_192000\
648 )
650 static struct snd_soc_dai_driver tas2562_dai_driver[] = {
651 {
652 .name = "tas2562 ASI1",
653 .id = 0,
654 .playback = {
655 .stream_name = "ASI1 Playback",
656 .channels_min = 2,
657 .channels_max = 2,
658 .rates = SNDRV_PCM_RATE_8000_192000,
659 .formats = TAS2562_FORMATS,
660 },
661 .capture = {
662 .stream_name = "ASI1 Capture",
663 .channels_min = 0,
664 .channels_max = 2,
665 .rates = SNDRV_PCM_RATE_8000_192000,
666 .formats = TAS2562_FORMATS,
667 },
668 .ops = &tas2562_dai_ops,
669 .symmetric_rates = 1,
670 },
671 };
673 static int tas2562_codec_probe(struct snd_soc_codec *codec)
674 {
675 int ret;
676 struct tas2562_priv *pTAS2562 = snd_soc_codec_get_drvdata(codec);
678 ret = snd_soc_add_codec_controls(codec, tas2562_controls,
679 ARRAY_SIZE(tas2562_controls));
680 if (ret < 0) {
681 pr_err("%s: add_codec_controls failed, err %d\n",
682 __func__, ret);
683 return ret;
684 }
686 tas2562_iv_enable(pTAS2562, 1);
687 pTAS2562->codec = codec;
688 dev_err(pTAS2562->dev, "%s\n", __func__);
690 return 0;
691 }
693 static int tas2562_codec_remove(struct snd_soc_codec *codec)
694 {
695 return 0;
696 }
698 static DECLARE_TLV_DB_SCALE(tas2562_digital_tlv, 1100, 50, 0);
700 static const struct snd_kcontrol_new tas2562_snd_controls[] = {
701 SOC_SINGLE_TLV("Amp Output Level", TAS2562_PlaybackConfigurationReg0,
702 0, 0x16, 0,
703 tas2562_digital_tlv),
704 };
706 static struct snd_soc_codec_driver soc_codec_driver_tas2562 = {
707 .probe = tas2562_codec_probe,
708 .remove = tas2562_codec_remove,
709 .read = tas2562_codec_read,
710 .write = tas2562_codec_write,
711 .suspend = tas2562_codec_suspend,
712 .resume = tas2562_codec_resume,
713 .component_driver = {
714 .controls = tas2562_snd_controls,
715 .num_controls = ARRAY_SIZE(tas2562_snd_controls),
716 .dapm_widgets = tas2562_dapm_widgets,
717 .num_dapm_widgets = ARRAY_SIZE(tas2562_dapm_widgets),
718 .dapm_routes = tas2562_audio_map,
719 .num_dapm_routes = ARRAY_SIZE(tas2562_audio_map),
720 },
721 };
723 int tas2562_register_codec(struct tas2562_priv *pTAS2562)
724 {
725 int nResult = 0;
727 dev_info(pTAS2562->dev, "%s, enter\n", __func__);
728 nResult = snd_soc_register_codec(pTAS2562->dev,
729 &soc_codec_driver_tas2562,
730 tas2562_dai_driver, ARRAY_SIZE(tas2562_dai_driver));
731 return nResult;
732 }
734 int tas2562_deregister_codec(struct tas2562_priv *pTAS2562)
735 {
736 snd_soc_unregister_codec(pTAS2562->dev);
738 return 0;
739 }
741 void tas2562_LoadConfig(struct tas2562_priv *pTAS2562)
742 {
743 int ret = 0;
745 if (hrtimer_active(&pTAS2562->mtimer))
746 {
747 dev_info(pTAS2562->dev, "cancel timer\n");
748 hrtimer_cancel(&pTAS2562->mtimer);
749 } else
750 dev_info(pTAS2562->dev, "timer not active\n");
752 pTAS2562->hw_reset(pTAS2562);
753 pTAS2562->write(pTAS2562, TAS2562_SoftwareReset,
754 TAS2562_SoftwareReset_SoftwareReset_Reset);
755 msleep(3);
757 pTAS2562->write(pTAS2562, TAS2562_MiscConfigurationReg0, 0xce);
759 ret = tas2562_set_slot(pTAS2562->codec, pTAS2562->mnSlot_width);
760 if (ret < 0)
761 goto end;
763 ret = tas2562_set_fmt(pTAS2562, pTAS2562->mnASIFormat);
764 if (ret < 0)
765 goto end;
767 ret = tas2562_set_bitwidth(pTAS2562, pTAS2562->mnPCMFormat);
768 if (ret < 0)
769 goto end;
771 ret = tas2562_set_samplerate(pTAS2562, pTAS2562->mnSamplingRate);
772 if (ret < 0)
773 goto end;
775 ret = tas2562_set_power_state(pTAS2562, pTAS2562->mnPowerState);
776 if (ret < 0)
777 goto end;
779 end:
780 /* power up failed, restart later */
781 if (ret < 0)
782 schedule_delayed_work(&pTAS2562->irq_work,
783 msecs_to_jiffies(1000));
784 }
786 MODULE_AUTHOR("Texas Instruments Inc.");
787 MODULE_DESCRIPTION("TAS2562 ALSA SOC Smart Amplifier driver");
788 MODULE_LICENSE("GPL v2");
789 #endif /* CONFIG_TAS2562_CODEC */