]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - tas2557sw-android/tas2557-stereo-driver.git/blob - tas2557-codec.c
Load calibration in the first playback
[tas2557sw-android/tas2557-stereo-driver.git] / tas2557-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 **     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;
103 static int tas2557_codec_resume(struct snd_soc_codec *pCodec)
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;
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)
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;
151 static void tas2557_shutdown(struct snd_pcm_substream *substream,
152         struct snd_soc_dai *dai)
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__);
160 static int tas2557_mute(struct snd_soc_dai *dai, int mute)
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;
174 static int tas2557_set_dai_sysclk(struct snd_soc_dai *pDAI,
175         int nClkID, unsigned int nFreqency, int nDir)
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;
185 static int tas2557_hw_params(struct snd_pcm_substream *pSubstream,
186         struct snd_pcm_hw_params *pParams, struct snd_soc_dai *pDAI)
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;
202 static int tas2557_set_dai_fmt(struct snd_soc_dai *pDAI, unsigned int nFormat)
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;
211 static int tas2557_prepare(struct snd_pcm_substream *pSubstream,
212         struct snd_soc_dai *pDAI)
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;
221 static int tas2557_set_bias_level(struct snd_soc_codec *pCodec,
222         enum snd_soc_bias_level eLevel)
224         struct tas2557_priv *pTAS2557 = snd_soc_codec_get_drvdata(pCodec);
226         dev_dbg(pTAS2557->dev, "%s: %d\n", __func__, eLevel);
227         return 0;
230 static int tas2557_codec_probe(struct snd_soc_codec *pCodec)
232         struct tas2557_priv *pTAS2557 = snd_soc_codec_get_drvdata(pCodec);
234         dev_dbg(pTAS2557->dev, "%s\n", __func__);
235         return 0;
238 static int tas2557_codec_remove(struct snd_soc_codec *pCodec)
240         return 0;
243 static int tas2557_power_ctrl_get(struct snd_kcontrol *pKcontrol,
244         struct snd_ctl_elem_value *pValue)
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;
263 static int tas2557_power_ctrl_put(struct snd_kcontrol *pKcontrol,
264         struct snd_ctl_elem_value *pValue)
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;
284 static int tas2557_fs_get(struct snd_kcontrol *pKcontrol,
285         struct snd_ctl_elem_value *pValue)
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;
306 static int tas2557_fs_put(struct snd_kcontrol *pKcontrol,
307         struct snd_ctl_elem_value *pValue)
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;
327 static int tas2557_DevA_Cali_get(struct snd_kcontrol *pKcontrol,
328         struct snd_ctl_elem_value *pValue)
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;
349 static int tas2557_DevB_Cali_get(struct snd_kcontrol *pKcontrol,
350         struct snd_ctl_elem_value *pValue)
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;
371 static int tas2557_program_get(struct snd_kcontrol *pKcontrol,
372         struct snd_ctl_elem_value *pValue)
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;
391 static int tas2557_program_put(struct snd_kcontrol *pKcontrol,
392         struct snd_ctl_elem_value *pValue)
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;
413 static int tas2557_configuration_get(struct snd_kcontrol *pKcontrol,
414         struct snd_ctl_elem_value *pValue)
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;
433 static int tas2557_configuration_put(struct snd_kcontrol *pKcontrol,
434         struct snd_ctl_elem_value *pValue)
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;
454 static int tas2557_calibration_get(struct snd_kcontrol *pKcontrol,
455         struct snd_ctl_elem_value *pValue)
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;
475 static int tas2557_calibration_put(struct snd_kcontrol *pKcontrol,
476         struct snd_ctl_elem_value *pValue)
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;
495 static int tas2557_ldac_gain_get(struct snd_kcontrol *pKcontrol,
496         struct snd_ctl_elem_value *pValue)
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;
518 static int tas2557_ldac_gain_put(struct snd_kcontrol *pKcontrol,
519         struct snd_ctl_elem_value *pValue)
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;
538 static int tas2557_rdac_gain_get(struct snd_kcontrol *pKcontrol,
539         struct snd_ctl_elem_value *pValue)
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;
562 static int tas2557_rdac_gain_put(struct snd_kcontrol *pKcontrol,
563         struct snd_ctl_elem_value *pValue)
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;
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)
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;
612 static int tas2557_dsp_chl_setup_put(struct snd_kcontrol *pKcontrol,
613                         struct snd_ctl_elem_value *pValue)
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;
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)
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;
662 static int tas2557_vboost_ctl_put(struct snd_kcontrol *pKcontrol,
663                         struct snd_ctl_elem_value *pValue)
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;
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)
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;
740 static int tas2557_vboost_volt_put(struct snd_kcontrol *pKcontrol,
741                         struct snd_ctl_elem_value *pValue)
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;
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)
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;
808 static int tas2557_echoref_ctl_put(struct snd_kcontrol *pKcontrol,
809                         struct snd_ctl_elem_value *pValue)
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;
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)
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;
943 int tas2557_deregister_codec(struct tas2557_priv *pTAS2557)
945         snd_soc_unregister_codec(pTAS2557->dev);
946         return 0;
949 MODULE_AUTHOR("Texas Instruments Inc.");
950 MODULE_DESCRIPTION("TAS2557 ALSA SOC Smart Amplifier Stereo driver");
951 MODULE_LICENSE("GPL v2");
952 #endif