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 ** tas2557-codec.c
15 **
16 ** Description:
17 ** ALSA SoC driver for Texas Instruments TAS2557 High Performance 4W Smart Amplifier
18 **
19 ** =============================================================================
20 */
22 #ifdef CONFIG_TAS2557_CODEC_STEREO
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 <linux/syscalls.h>
39 #include <linux/fcntl.h>
40 #include <linux/uaccess.h>
41 #include <sound/core.h>
42 #include <sound/pcm.h>
43 #include <sound/pcm_params.h>
44 #include <sound/soc.h>
45 #include <sound/initval.h>
46 #include <sound/tlv.h>
48 #include "tas2557-core.h"
49 #include "tas2557-codec.h"
51 #define KCONTROL_CODEC
53 static unsigned int tas2557_codec_read(struct snd_soc_codec *pCodec,
54 unsigned int nRegister)
55 {
56 struct tas2557_priv *pTAS2557 = snd_soc_codec_get_drvdata(pCodec);
57 int ret = 0;
58 unsigned int Value = 0;
60 mutex_lock(&pTAS2557->codec_lock);
62 ret = pTAS2557->read(pTAS2557,
63 pTAS2557->mnCurrentChannel, nRegister, &Value);
64 if (ret < 0)
65 dev_err(pTAS2557->dev, "%s, %d, ERROR happen=%d\n", __func__,
66 __LINE__, ret);
67 else
68 ret = Value;
70 mutex_unlock(&pTAS2557->codec_lock);
71 return ret;
72 }
74 static int tas2557_codec_write(struct snd_soc_codec *pCodec, unsigned int nRegister,
75 unsigned int nValue)
76 {
77 struct tas2557_priv *pTAS2557 = snd_soc_codec_get_drvdata(pCodec);
78 int ret = 0;
80 mutex_lock(&pTAS2557->codec_lock);
82 ret = pTAS2557->write(pTAS2557,
83 pTAS2557->mnCurrentChannel, nRegister, nValue);
85 mutex_unlock(&pTAS2557->codec_lock);
86 return ret;
87 }
89 static int tas2557_codec_suspend(struct snd_soc_codec *pCodec)
90 {
91 struct tas2557_priv *pTAS2557 = snd_soc_codec_get_drvdata(pCodec);
92 int ret = 0;
94 mutex_lock(&pTAS2557->codec_lock);
96 dev_dbg(pTAS2557->dev, "%s\n", __func__);
97 pTAS2557->runtime_suspend(pTAS2557);
99 mutex_unlock(&pTAS2557->codec_lock);
100 return ret;
101 }
103 static int tas2557_codec_resume(struct snd_soc_codec *pCodec)
104 {
105 struct tas2557_priv *pTAS2557 = snd_soc_codec_get_drvdata(pCodec);
106 int ret = 0;
108 mutex_lock(&pTAS2557->codec_lock);
110 dev_dbg(pTAS2557->dev, "%s\n", __func__);
111 pTAS2557->runtime_resume(pTAS2557);
113 mutex_unlock(&pTAS2557->codec_lock);
114 return ret;
115 }
117 static const struct snd_soc_dapm_widget tas2557_dapm_widgets[] = {
118 SND_SOC_DAPM_AIF_IN("Stereo ASI1", "Stereo ASI1 Playback", 0, SND_SOC_NOPM, 0, 0),
119 SND_SOC_DAPM_AIF_IN("Stereo ASI2", "Stereo ASI2 Playback", 0, SND_SOC_NOPM, 0, 0),
120 SND_SOC_DAPM_AIF_IN("Stereo ASIM", "Stereo ASIM Playback", 0, SND_SOC_NOPM, 0, 0),
121 SND_SOC_DAPM_DAC("Stereo DAC", NULL, SND_SOC_NOPM, 0, 0),
123 SND_SOC_DAPM_OUT_DRV("Stereo ClassD", SND_SOC_NOPM, 0, 0, NULL, 0),
125 SND_SOC_DAPM_SUPPLY("Stereo PLL", SND_SOC_NOPM, 0, 0, NULL, 0),
126 SND_SOC_DAPM_SUPPLY("Stereo NDivider", SND_SOC_NOPM, 0, 0, NULL, 0),
128 SND_SOC_DAPM_OUTPUT("Stereo OUT")
129 };
131 static const struct snd_soc_dapm_route tas2557_audio_map[] = {
132 {"Stereo DAC", NULL, "Stereo ASI1"},
133 {"Stereo DAC", NULL, "Stereo ASI2"},
134 {"Stereo DAC", NULL, "Stereo ASIM"},
135 {"Stereo ClassD", NULL, "Stereo DAC"},
136 {"Stereo OUT", NULL, "Stereo ClassD"},
137 {"Stereo DAC", NULL, "Stereo PLL"},
138 {"Stereo DAC", NULL, "Stereo NDivider"},
139 };
141 static int tas2557_startup(struct snd_pcm_substream *substream,
142 struct snd_soc_dai *dai)
143 {
144 struct snd_soc_codec *codec = dai->codec;
145 struct tas2557_priv *pTAS2557 = snd_soc_codec_get_drvdata(codec);
147 dev_dbg(pTAS2557->dev, "%s\n", __func__);
148 return 0;
149 }
151 static void tas2557_shutdown(struct snd_pcm_substream *substream,
152 struct snd_soc_dai *dai)
153 {
154 struct snd_soc_codec *codec = dai->codec;
155 struct tas2557_priv *pTAS2557 = snd_soc_codec_get_drvdata(codec);
157 dev_dbg(pTAS2557->dev, "%s\n", __func__);
158 }
160 static int tas2557_mute(struct snd_soc_dai *dai, int mute)
161 {
162 struct snd_soc_codec *codec = dai->codec;
163 struct tas2557_priv *pTAS2557 = snd_soc_codec_get_drvdata(codec);
165 mutex_lock(&pTAS2557->codec_lock);
167 dev_dbg(pTAS2557->dev, "%s\n", __func__);
168 tas2557_enable(pTAS2557, !mute);
170 mutex_unlock(&pTAS2557->codec_lock);
171 return 0;
172 }
174 static int tas2557_set_dai_sysclk(struct snd_soc_dai *pDAI,
175 int nClkID, unsigned int nFreqency, int nDir)
176 {
177 struct snd_soc_codec *pCodec = pDAI->codec;
178 struct tas2557_priv *pTAS2557 = snd_soc_codec_get_drvdata(pCodec);
180 dev_dbg(pTAS2557->dev, "tas2557_set_dai_sysclk: freq = %u\n", nFreqency);
182 return 0;
183 }
185 static int tas2557_hw_params(struct snd_pcm_substream *pSubstream,
186 struct snd_pcm_hw_params *pParams, struct snd_soc_dai *pDAI)
187 {
188 struct snd_soc_codec *pCodec = pDAI->codec;
189 struct tas2557_priv *pTAS2557 = snd_soc_codec_get_drvdata(pCodec);
191 mutex_lock(&pTAS2557->codec_lock);
193 dev_dbg(pTAS2557->dev, "%s\n", __func__);
194 /* do bit rate setting during platform data */
195 /* tas2557_set_bit_rate(pTAS2557, channel_both, snd_pcm_format_width(params_format(pParams))); */
196 tas2557_set_sampling_rate(pTAS2557, params_rate(pParams));
198 mutex_unlock(&pTAS2557->codec_lock);
199 return 0;
200 }
202 static int tas2557_set_dai_fmt(struct snd_soc_dai *pDAI, unsigned int nFormat)
203 {
204 struct snd_soc_codec *codec = pDAI->codec;
205 struct tas2557_priv *pTAS2557 = snd_soc_codec_get_drvdata(codec);
207 dev_dbg(pTAS2557->dev, "%s\n", __func__);
208 return 0;
209 }
211 static int tas2557_prepare(struct snd_pcm_substream *pSubstream,
212 struct snd_soc_dai *pDAI)
213 {
214 struct snd_soc_codec *codec = pDAI->codec;
215 struct tas2557_priv *pTAS2557 = snd_soc_codec_get_drvdata(codec);
217 dev_dbg(pTAS2557->dev, "%s\n", __func__);
218 return 0;
219 }
221 static int tas2557_set_bias_level(struct snd_soc_codec *pCodec,
222 enum snd_soc_bias_level eLevel)
223 {
224 struct tas2557_priv *pTAS2557 = snd_soc_codec_get_drvdata(pCodec);
226 dev_dbg(pTAS2557->dev, "%s: %d\n", __func__, eLevel);
227 return 0;
228 }
230 static int tas2557_codec_probe(struct snd_soc_codec *pCodec)
231 {
232 struct tas2557_priv *pTAS2557 = snd_soc_codec_get_drvdata(pCodec);
234 dev_dbg(pTAS2557->dev, "%s\n", __func__);
235 return 0;
236 }
238 static int tas2557_codec_remove(struct snd_soc_codec *pCodec)
239 {
240 return 0;
241 }
243 static int tas2557_power_ctrl_get(struct snd_kcontrol *pKcontrol,
244 struct snd_ctl_elem_value *pValue)
245 {
246 #ifdef KCONTROL_CODEC
247 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(pKcontrol);
248 #else
249 struct snd_soc_codec *codec = snd_kcontrol_chip(pKcontrol);
250 #endif
251 struct tas2557_priv *pTAS2557 = snd_soc_codec_get_drvdata(codec);
253 mutex_lock(&pTAS2557->codec_lock);
255 pValue->value.integer.value[0] = pTAS2557->mbPowerUp;
256 dev_dbg(pTAS2557->dev, "tas2557_power_ctrl_get = %d\n",
257 pTAS2557->mbPowerUp);
259 mutex_unlock(&pTAS2557->codec_lock);
260 return 0;
261 }
263 static int tas2557_power_ctrl_put(struct snd_kcontrol *pKcontrol,
264 struct snd_ctl_elem_value *pValue)
265 {
266 #ifdef KCONTROL_CODEC
267 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(pKcontrol);
268 #else
269 struct snd_soc_codec *codec = snd_kcontrol_chip(pKcontrol);
270 #endif
271 struct tas2557_priv *pTAS2557 = snd_soc_codec_get_drvdata(codec);
273 int nPowerOn = pValue->value.integer.value[0];
275 mutex_lock(&pTAS2557->codec_lock);
277 dev_dbg(pTAS2557->dev, "tas2557_power_ctrl_put = %d\n", nPowerOn);
278 tas2557_enable(pTAS2557, (nPowerOn != 0));
280 mutex_unlock(&pTAS2557->codec_lock);
281 return 0;
282 }
284 static int tas2557_fs_get(struct snd_kcontrol *pKcontrol,
285 struct snd_ctl_elem_value *pValue)
286 {
287 #ifdef KCONTROL_CODEC
288 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(pKcontrol);
289 #else
290 struct snd_soc_codec *codec = snd_kcontrol_chip(pKcontrol);
291 #endif
292 struct tas2557_priv *pTAS2557 = snd_soc_codec_get_drvdata(codec);
293 int nFS = 48000;
295 mutex_lock(&pTAS2557->codec_lock);
297 if (pTAS2557->mpFirmware->mnConfigurations)
298 nFS = pTAS2557->mpFirmware->mpConfigurations[pTAS2557->mnCurrentConfiguration].mnSamplingRate;
299 pValue->value.integer.value[0] = nFS;
300 dev_dbg(pTAS2557->dev, "tas2557_fs_get = %d\n", nFS);
302 mutex_unlock(&pTAS2557->codec_lock);
303 return 0;
304 }
306 static int tas2557_fs_put(struct snd_kcontrol *pKcontrol,
307 struct snd_ctl_elem_value *pValue)
308 {
309 #ifdef KCONTROL_CODEC
310 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(pKcontrol);
311 #else
312 struct snd_soc_codec *codec = snd_kcontrol_chip(pKcontrol);
313 #endif
314 struct tas2557_priv *pTAS2557 = snd_soc_codec_get_drvdata(codec);
315 int ret = 0;
316 int nFS = pValue->value.integer.value[0];
318 mutex_lock(&pTAS2557->codec_lock);
320 dev_info(pTAS2557->dev, "tas2557_fs_put = %d\n", nFS);
321 ret = tas2557_set_sampling_rate(pTAS2557, nFS);
323 mutex_unlock(&pTAS2557->codec_lock);
324 return ret;
325 }
327 static int tas2557_DevA_Cali_get(struct snd_kcontrol *pKcontrol,
328 struct snd_ctl_elem_value *pValue)
329 {
330 #ifdef KCONTROL_CODEC
331 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(pKcontrol);
332 #else
333 struct snd_soc_codec *codec = snd_kcontrol_chip(pKcontrol);
334 #endif
335 struct tas2557_priv *pTAS2557 = snd_soc_codec_get_drvdata(codec);
336 bool ret = 0;
337 int prm_r0 = 0;
339 mutex_lock(&pTAS2557->codec_lock);
341 ret = tas2557_get_Cali_prm_r0(pTAS2557, channel_left, &prm_r0);
342 if (ret)
343 pValue->value.integer.value[0] = prm_r0;
345 mutex_unlock(&pTAS2557->codec_lock);
346 return 0;
347 }
349 static int tas2557_DevB_Cali_get(struct snd_kcontrol *pKcontrol,
350 struct snd_ctl_elem_value *pValue)
351 {
352 #ifdef KCONTROL_CODEC
353 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(pKcontrol);
354 #else
355 struct snd_soc_codec *codec = snd_kcontrol_chip(pKcontrol);
356 #endif
357 struct tas2557_priv *pTAS2557 = snd_soc_codec_get_drvdata(codec);
358 bool ret = 0;
359 int prm_r0 = 0;
361 mutex_lock(&pTAS2557->codec_lock);
363 ret = tas2557_get_Cali_prm_r0(pTAS2557, channel_right, &prm_r0);
364 if (ret)
365 pValue->value.integer.value[0] = prm_r0;
367 mutex_unlock(&pTAS2557->codec_lock);
368 return 0;
369 }
371 static int tas2557_program_get(struct snd_kcontrol *pKcontrol,
372 struct snd_ctl_elem_value *pValue)
373 {
374 #ifdef KCONTROL_CODEC
375 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(pKcontrol);
376 #else
377 struct snd_soc_codec *codec = snd_kcontrol_chip(pKcontrol);
378 #endif
379 struct tas2557_priv *pTAS2557 = snd_soc_codec_get_drvdata(codec);
381 mutex_lock(&pTAS2557->codec_lock);
383 pValue->value.integer.value[0] = pTAS2557->mnCurrentProgram;
384 dev_dbg(pTAS2557->dev, "tas2557_program_get = %d\n",
385 pTAS2557->mnCurrentProgram);
387 mutex_unlock(&pTAS2557->codec_lock);
388 return 0;
389 }
391 static int tas2557_program_put(struct snd_kcontrol *pKcontrol,
392 struct snd_ctl_elem_value *pValue)
393 {
394 #ifdef KCONTROL_CODEC
395 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(pKcontrol);
396 #else
397 struct snd_soc_codec *codec = snd_kcontrol_chip(pKcontrol);
398 #endif
399 struct tas2557_priv *pTAS2557 = snd_soc_codec_get_drvdata(codec);
400 unsigned int nProgram = pValue->value.integer.value[0];
401 int ret = 0, nConfiguration = -1;
403 mutex_lock(&pTAS2557->codec_lock);
405 if (nProgram == pTAS2557->mnCurrentProgram)
406 nConfiguration = pTAS2557->mnCurrentConfiguration;
407 ret = tas2557_set_program(pTAS2557, nProgram, nConfiguration);
409 mutex_unlock(&pTAS2557->codec_lock);
410 return ret;
411 }
413 static int tas2557_configuration_get(struct snd_kcontrol *pKcontrol,
414 struct snd_ctl_elem_value *pValue)
415 {
416 #ifdef KCONTROL_CODEC
417 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(pKcontrol);
418 #else
419 struct snd_soc_codec *codec = snd_kcontrol_chip(pKcontrol);
420 #endif
421 struct tas2557_priv *pTAS2557 = snd_soc_codec_get_drvdata(codec);
423 mutex_lock(&pTAS2557->codec_lock);
425 pValue->value.integer.value[0] = pTAS2557->mnCurrentConfiguration;
426 dev_dbg(pTAS2557->dev, "tas2557_configuration_get = %d\n",
427 pTAS2557->mnCurrentConfiguration);
429 mutex_unlock(&pTAS2557->codec_lock);
430 return 0;
431 }
433 static int tas2557_configuration_put(struct snd_kcontrol *pKcontrol,
434 struct snd_ctl_elem_value *pValue)
435 {
436 #ifdef KCONTROL_CODEC
437 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(pKcontrol);
438 #else
439 struct snd_soc_codec *codec = snd_kcontrol_chip(pKcontrol);
440 #endif
441 struct tas2557_priv *pTAS2557 = snd_soc_codec_get_drvdata(codec);
442 unsigned int nConfiguration = pValue->value.integer.value[0];
443 int ret = 0;
445 mutex_lock(&pTAS2557->codec_lock);
447 dev_info(pTAS2557->dev, "%s = %d\n", __func__, nConfiguration);
448 ret = tas2557_set_config(pTAS2557, nConfiguration);
450 mutex_unlock(&pTAS2557->codec_lock);
451 return ret;
452 }
454 static int tas2557_calibration_get(struct snd_kcontrol *pKcontrol,
455 struct snd_ctl_elem_value *pValue)
456 {
457 #ifdef KCONTROL_CODEC
458 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(pKcontrol);
459 #else
460 struct snd_soc_codec *codec = snd_kcontrol_chip(pKcontrol);
461 #endif
462 struct tas2557_priv *pTAS2557 = snd_soc_codec_get_drvdata(codec);
464 mutex_lock(&pTAS2557->codec_lock);
466 pValue->value.integer.value[0] = pTAS2557->mnCurrentCalibration;
467 dev_info(pTAS2557->dev,
468 "tas2557_calibration_get = %d\n",
469 pTAS2557->mnCurrentCalibration);
471 mutex_unlock(&pTAS2557->codec_lock);
472 return 0;
473 }
475 static int tas2557_calibration_put(struct snd_kcontrol *pKcontrol,
476 struct snd_ctl_elem_value *pValue)
477 {
478 #ifdef KCONTROL_CODEC
479 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(pKcontrol);
480 #else
481 struct snd_soc_codec *codec = snd_kcontrol_chip(pKcontrol);
482 #endif
483 struct tas2557_priv *pTAS2557 = snd_soc_codec_get_drvdata(codec);
484 unsigned int nCalibration = pValue->value.integer.value[0];
485 int ret = 0;
487 mutex_lock(&pTAS2557->codec_lock);
489 ret = tas2557_set_calibration(pTAS2557, nCalibration);
491 mutex_unlock(&pTAS2557->codec_lock);
492 return ret;
493 }
495 static int tas2557_ldac_gain_get(struct snd_kcontrol *pKcontrol,
496 struct snd_ctl_elem_value *pValue)
497 {
498 #ifdef KCONTROL_CODEC
499 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(pKcontrol);
500 #else
501 struct snd_soc_codec *codec = snd_kcontrol_chip(pKcontrol);
502 #endif
503 struct tas2557_priv *pTAS2557 = snd_soc_codec_get_drvdata(codec);
504 unsigned char nGain = 0;
505 int ret = -1;
507 mutex_lock(&pTAS2557->codec_lock);
509 ret = tas2557_get_DAC_gain(pTAS2557, channel_left, &nGain);
510 if (ret >= 0)
511 pValue->value.integer.value[0] = nGain;
512 dev_dbg(pTAS2557->dev, "%s, ret = %d, %d\n", __func__, ret, nGain);
514 mutex_unlock(&pTAS2557->codec_lock);
515 return ret;
516 }
518 static int tas2557_ldac_gain_put(struct snd_kcontrol *pKcontrol,
519 struct snd_ctl_elem_value *pValue)
520 {
521 #ifdef KCONTROL_CODEC
522 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(pKcontrol);
523 #else
524 struct snd_soc_codec *codec = snd_kcontrol_chip(pKcontrol);
525 #endif
526 struct tas2557_priv *pTAS2557 = snd_soc_codec_get_drvdata(codec);
527 unsigned int nGain = pValue->value.integer.value[0];
528 int ret = 0;
530 mutex_lock(&pTAS2557->codec_lock);
532 ret = tas2557_set_DAC_gain(pTAS2557, channel_left, nGain);
534 mutex_unlock(&pTAS2557->codec_lock);
535 return ret;
536 }
538 static int tas2557_rdac_gain_get(struct snd_kcontrol *pKcontrol,
539 struct snd_ctl_elem_value *pValue)
540 {
541 #ifdef KCONTROL_CODEC
542 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(pKcontrol);
543 #else
544 struct snd_soc_codec *codec = snd_kcontrol_chip(pKcontrol);
545 #endif
546 struct tas2557_priv *pTAS2557 = snd_soc_codec_get_drvdata(codec);
547 unsigned char nGain = 0;
548 int ret = -1;
550 mutex_lock(&pTAS2557->codec_lock);
552 ret = tas2557_get_DAC_gain(pTAS2557, channel_right, &nGain);
553 if (ret >= 0)
554 pValue->value.integer.value[0] = nGain;
555 dev_dbg(pTAS2557->dev, "%s, ret = %d, %d\n", __func__, ret, nGain);
557 mutex_unlock(&pTAS2557->codec_lock);
559 return ret;
560 }
562 static int tas2557_rdac_gain_put(struct snd_kcontrol *pKcontrol,
563 struct snd_ctl_elem_value *pValue)
564 {
565 #ifdef KCONTROL_CODEC
566 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(pKcontrol);
567 #else
568 struct snd_soc_codec *codec = snd_kcontrol_chip(pKcontrol);
569 #endif
570 struct tas2557_priv *pTAS2557 = snd_soc_codec_get_drvdata(codec);
571 unsigned int nGain = pValue->value.integer.value[0];
572 int ret = 0;
574 mutex_lock(&pTAS2557->codec_lock);
576 ret = tas2557_set_DAC_gain(pTAS2557, channel_right, nGain);
578 mutex_unlock(&pTAS2557->codec_lock);
579 return ret;
580 }
582 static const char * const chl_setup_text[] = {
583 "default",
584 "DevA-Mute-DevB-Mute",
585 "DevA-Left-DevB-Right",
586 "DevA-Right-DevB-Left",
587 "DevA-MonoMix-DevB-MonoMix"
588 };
589 static const struct soc_enum chl_setup_enum[] = {
590 SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(chl_setup_text), chl_setup_text),
591 };
593 static int tas2557_dsp_chl_setup_get(struct snd_kcontrol *pKcontrol,
594 struct snd_ctl_elem_value *pValue)
595 {
596 #ifdef KCONTROL_CODEC
597 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(pKcontrol);
598 #else
599 struct snd_soc_codec *codec = snd_kcontrol_chip(pKcontrol);
600 #endif
601 struct tas2557_priv *pTAS2557 = snd_soc_codec_get_drvdata(codec);
603 mutex_lock(&pTAS2557->codec_lock);
605 pValue->value.integer.value[0] = pTAS2557->mnChannelState;
607 mutex_unlock(&pTAS2557->codec_lock);
609 return 0;
610 }
612 static int tas2557_dsp_chl_setup_put(struct snd_kcontrol *pKcontrol,
613 struct snd_ctl_elem_value *pValue)
614 {
615 #ifdef KCONTROL_CODEC
616 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(pKcontrol);
617 #else
618 struct snd_soc_codec *codec = snd_kcontrol_chip(pKcontrol);
619 #endif
620 struct tas2557_priv *pTAS2557 = snd_soc_codec_get_drvdata(codec);
621 int channel_state = pValue->value.integer.value[0];
623 mutex_lock(&pTAS2557->codec_lock);
625 tas2557_SA_DevChnSetup(pTAS2557, channel_state);
627 mutex_unlock(&pTAS2557->codec_lock);
628 return 0;
629 }
631 static const char * const vboost_ctl_text[] = {
632 "default",
633 "Device(s) AlwaysOn"
634 };
636 static const struct soc_enum vboost_ctl_enum[] = {
637 SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(vboost_ctl_text), vboost_ctl_text),
638 };
640 static int tas2557_vboost_ctl_get(struct snd_kcontrol *pKcontrol,
641 struct snd_ctl_elem_value *pValue)
642 {
643 #ifdef KCONTROL_CODEC
644 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(pKcontrol);
645 #else
646 struct snd_soc_codec *codec = snd_kcontrol_chip(pKcontrol);
647 #endif
648 struct tas2557_priv *pTAS2557 = snd_soc_codec_get_drvdata(codec);
649 int nResult = 0, nVBoost = 0;
651 mutex_lock(&pTAS2557->codec_lock);
653 nResult = tas2557_get_VBoost(pTAS2557, &nVBoost);
654 if (nResult >= 0)
655 pValue->value.integer.value[0] = nVBoost;
657 mutex_unlock(&pTAS2557->codec_lock);
659 return 0;
660 }
662 static int tas2557_vboost_ctl_put(struct snd_kcontrol *pKcontrol,
663 struct snd_ctl_elem_value *pValue)
664 {
665 #ifdef KCONTROL_CODEC
666 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(pKcontrol);
667 #else
668 struct snd_soc_codec *codec = snd_kcontrol_chip(pKcontrol);
669 #endif
670 struct tas2557_priv *pTAS2557 = snd_soc_codec_get_drvdata(codec);
671 int vboost_state = pValue->value.integer.value[0];
673 mutex_lock(&pTAS2557->codec_lock);
675 tas2557_set_VBoost(pTAS2557, vboost_state, pTAS2557->mbPowerUp);
677 mutex_unlock(&pTAS2557->codec_lock);
678 return 0;
679 }
681 static const char * const vboost_volt_text[] = {
682 "8.6V",
683 "8.1V",
684 "7.6V",
685 "6.6V",
686 "5.6V"
687 };
689 static const struct soc_enum vboost_volt_enum[] = {
690 SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(vboost_volt_text), vboost_volt_text),
691 };
693 static int tas2557_vboost_volt_get(struct snd_kcontrol *pKcontrol,
694 struct snd_ctl_elem_value *pValue)
695 {
696 #ifdef KCONTROL_CODEC
697 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(pKcontrol);
698 #else
699 struct snd_soc_codec *codec = snd_kcontrol_chip(pKcontrol);
700 #endif
701 struct tas2557_priv *pTAS2557 = snd_soc_codec_get_drvdata(codec);
702 int nVBstVolt = 0;
704 mutex_lock(&pTAS2557->codec_lock);
706 dev_dbg(pTAS2557->dev, "%s, VBoost volt %d\n", __func__, pTAS2557->mnVBoostVoltage);
707 switch (pTAS2557->mnVBoostVoltage) {
708 case TAS2557_VBST_8P5V:
709 nVBstVolt = 0;
710 break;
712 case TAS2557_VBST_8P1V:
713 nVBstVolt = 1;
714 break;
716 case TAS2557_VBST_7P6V:
717 nVBstVolt = 2;
718 break;
720 case TAS2557_VBST_6P6V:
721 nVBstVolt = 3;
722 break;
724 case TAS2557_VBST_5P6V:
725 nVBstVolt = 4;
726 break;
728 default:
729 dev_err(pTAS2557->dev, "%s, error volt %d\n", __func__, pTAS2557->mnVBoostVoltage);
730 break;
731 }
733 pValue->value.integer.value[0] = nVBstVolt;
735 mutex_unlock(&pTAS2557->codec_lock);
737 return 0;
738 }
740 static int tas2557_vboost_volt_put(struct snd_kcontrol *pKcontrol,
741 struct snd_ctl_elem_value *pValue)
742 {
743 #ifdef KCONTROL_CODEC
744 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(pKcontrol);
745 #else
746 struct snd_soc_codec *codec = snd_kcontrol_chip(pKcontrol);
747 #endif
748 struct tas2557_priv *pTAS2557 = snd_soc_codec_get_drvdata(codec);
749 int vbstvolt = pValue->value.integer.value[0];
751 mutex_lock(&pTAS2557->codec_lock);
753 dev_dbg(pTAS2557->dev, "%s, volt %d\n", __func__, vbstvolt);
754 switch (vbstvolt) {
755 case 0:
756 pTAS2557->mnVBoostVoltage = TAS2557_VBST_8P5V;
757 break;
759 case 1:
760 pTAS2557->mnVBoostVoltage = TAS2557_VBST_8P1V;
761 break;
763 case 2:
764 pTAS2557->mnVBoostVoltage = TAS2557_VBST_7P6V;
765 break;
767 case 3:
768 pTAS2557->mnVBoostVoltage = TAS2557_VBST_6P6V;
769 break;
771 case 4:
772 pTAS2557->mnVBoostVoltage = TAS2557_VBST_5P6V;
773 break;
775 default:
776 dev_err(pTAS2557->dev, "%s, error volt %d\n", __func__, vbstvolt);
777 break;
778 }
780 mutex_unlock(&pTAS2557->codec_lock);
781 return 0;
782 }
784 static const char * const echoref_ctl_text[] = {"left channel", "right channel", "both channel"};
785 static const struct soc_enum echoref_ctl_enum[] = {
786 SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(echoref_ctl_text), echoref_ctl_text),
787 };
789 static int tas2557_echoref_ctl_get(struct snd_kcontrol *pKcontrol,
790 struct snd_ctl_elem_value *pValue)
791 {
792 #ifdef KCONTROL_CODEC
793 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(pKcontrol);
794 #else
795 struct snd_soc_codec *codec = snd_kcontrol_chip(pKcontrol);
796 #endif
797 struct tas2557_priv *pTAS2557 = snd_soc_codec_get_drvdata(codec);
799 mutex_lock(&pTAS2557->codec_lock);
801 pValue->value.integer.value[0] = pTAS2557->mnEchoRef;
803 mutex_unlock(&pTAS2557->codec_lock);
805 return 0;
806 }
808 static int tas2557_echoref_ctl_put(struct snd_kcontrol *pKcontrol,
809 struct snd_ctl_elem_value *pValue)
810 {
811 #ifdef KCONTROL_CODEC
812 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(pKcontrol);
813 #else
814 struct snd_soc_codec *codec = snd_kcontrol_chip(pKcontrol);
815 #endif
816 struct tas2557_priv *pTAS2557 = snd_soc_codec_get_drvdata(codec);
817 int echoref = pValue->value.integer.value[0]&0x01; /* only take care of left/right channel switch */
819 mutex_lock(&pTAS2557->codec_lock);
821 if (echoref != pTAS2557->mnEchoRef) {
822 pTAS2557->mnEchoRef = echoref;
823 tas2557_SA_ctl_echoRef(pTAS2557);
824 }
826 mutex_unlock(&pTAS2557->codec_lock);
827 return 0;
828 }
830 static const struct snd_kcontrol_new tas2557_snd_controls[] = {
831 SOC_SINGLE_EXT("Stereo LDAC Playback Volume", SND_SOC_NOPM, 0, 0x0f, 0,
832 tas2557_ldac_gain_get, tas2557_ldac_gain_put),
833 SOC_SINGLE_EXT("Stereo RDAC Playback Volume", SND_SOC_NOPM, 0, 0x0f, 0,
834 tas2557_rdac_gain_get, tas2557_rdac_gain_put),
835 SOC_SINGLE_EXT("Stereo PowerCtrl", SND_SOC_NOPM, 0, 0x0001, 0,
836 tas2557_power_ctrl_get, tas2557_power_ctrl_put),
837 SOC_SINGLE_EXT("Stereo Program", SND_SOC_NOPM, 0, 0x00FF, 0,
838 tas2557_program_get, tas2557_program_put),
839 SOC_SINGLE_EXT("Stereo Configuration", SND_SOC_NOPM, 0, 0x00FF, 0,
840 tas2557_configuration_get, tas2557_configuration_put),
841 SOC_SINGLE_EXT("Stereo FS", SND_SOC_NOPM, 8000, 48000, 0,
842 tas2557_fs_get, tas2557_fs_put),
843 SOC_SINGLE_EXT("Get DevA Cali_Re", SND_SOC_NOPM, 0, 0x7f000000, 0,
844 tas2557_DevA_Cali_get, NULL),
845 SOC_SINGLE_EXT("Get DevB Cali_Re", SND_SOC_NOPM, 0, 0x7f000000, 0,
846 tas2557_DevB_Cali_get, NULL),
847 SOC_SINGLE_EXT("Stereo Calibration", SND_SOC_NOPM, 0, 0x00FF, 0,
848 tas2557_calibration_get, tas2557_calibration_put),
849 SOC_ENUM_EXT("Stereo DSPChl Setup", chl_setup_enum[0],
850 tas2557_dsp_chl_setup_get, tas2557_dsp_chl_setup_put),
851 SOC_ENUM_EXT("VBoost Ctrl", vboost_ctl_enum[0],
852 tas2557_vboost_ctl_get, tas2557_vboost_ctl_put),
853 SOC_ENUM_EXT("VBoost Volt", vboost_volt_enum[0],
854 tas2557_vboost_volt_get, tas2557_vboost_volt_put),
855 SOC_ENUM_EXT("Stereo EchoRef Ctrl", echoref_ctl_enum[0],
856 tas2557_echoref_ctl_get, tas2557_echoref_ctl_put),
857 };
859 static struct snd_soc_codec_driver soc_codec_driver_tas2557 = {
860 .probe = tas2557_codec_probe,
861 .remove = tas2557_codec_remove,
862 .read = tas2557_codec_read,
863 .write = tas2557_codec_write,
864 .suspend = tas2557_codec_suspend,
865 .resume = tas2557_codec_resume,
866 .set_bias_level = tas2557_set_bias_level,
867 .idle_bias_off = true,
868 .component_driver = {
869 .controls = tas2557_snd_controls,
870 .num_controls = ARRAY_SIZE(tas2557_snd_controls),
871 .dapm_widgets = tas2557_dapm_widgets,
872 .num_dapm_widgets = ARRAY_SIZE(tas2557_dapm_widgets),
873 .dapm_routes = tas2557_audio_map,
874 .num_dapm_routes = ARRAY_SIZE(tas2557_audio_map),
875 },
876 };
878 static struct snd_soc_dai_ops tas2557_dai_ops = {
879 .startup = tas2557_startup,
880 .shutdown = tas2557_shutdown,
881 .digital_mute = tas2557_mute,
882 .hw_params = tas2557_hw_params,
883 .prepare = tas2557_prepare,
884 .set_sysclk = tas2557_set_dai_sysclk,
885 .set_fmt = tas2557_set_dai_fmt,
886 };
888 #define TAS2557_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
889 SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
890 static struct snd_soc_dai_driver tas2557_dai_driver[] = {
891 {
892 .name = "tas2557 Stereo ASI1",
893 .id = 0,
894 .playback = {
895 .stream_name = "Stereo ASI1 Playback",
896 .channels_min = 2,
897 .channels_max = 2,
898 .rates = SNDRV_PCM_RATE_8000_192000,
899 .formats = TAS2557_FORMATS,
900 },
901 .ops = &tas2557_dai_ops,
902 .symmetric_rates = 1,
903 },
904 {
905 .name = "tas2557 Stereo ASI2",
906 .id = 1,
907 .playback = {
908 .stream_name = "Stereo ASI2 Playback",
909 .channels_min = 2,
910 .channels_max = 2,
911 .rates = SNDRV_PCM_RATE_8000_192000,
912 .formats = TAS2557_FORMATS,
913 },
914 .ops = &tas2557_dai_ops,
915 .symmetric_rates = 1,
916 },
917 {
918 .name = "tas2557 Stereo ASIM",
919 .id = 2,
920 .playback = {
921 .stream_name = "Stereo ASIM Playback",
922 .channels_min = 2,
923 .channels_max = 2,
924 .rates = SNDRV_PCM_RATE_8000_192000,
925 .formats = TAS2557_FORMATS,
926 },
927 .ops = &tas2557_dai_ops,
928 .symmetric_rates = 1,
929 },
930 };
932 int tas2557_register_codec(struct tas2557_priv *pTAS2557)
933 {
934 int nResult = 0;
936 dev_info(pTAS2557->dev, "%s, enter\n", __func__);
937 nResult = snd_soc_register_codec(pTAS2557->dev,
938 &soc_codec_driver_tas2557,
939 tas2557_dai_driver, ARRAY_SIZE(tas2557_dai_driver));
940 return nResult;
941 }
943 int tas2557_deregister_codec(struct tas2557_priv *pTAS2557)
944 {
945 snd_soc_unregister_codec(pTAS2557->dev);
946 return 0;
947 }
949 MODULE_AUTHOR("Texas Instruments Inc.");
950 MODULE_DESCRIPTION("TAS2557 ALSA SOC Smart Amplifier Stereo driver");
951 MODULE_LICENSE("GPL v2");
952 #endif