stereo solution first commit
[tas2555sw-android/tas2555-android-device-driver-stereo.git] / tas2555-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 ** You should have received a copy of the GNU General Public License along with
14 ** this program; if not, write to the Free Software Foundation, Inc., 51 Franklin
15 ** Street, Fifth Floor, Boston, MA 02110-1301, USA.
16 **
17 ** File:
18 **     tas2555-codec.c
19 **
20 ** Description:
21 **     ALSA SoC driver for Texas Instruments TAS2555 High Performance 4W Smart Amplifier
22 **
23 ** =============================================================================
24 */
26 #ifdef CONFIG_TAS2555_CODEC_STEREO
28 #define DEBUG
29 #include <linux/module.h>
30 #include <linux/moduleparam.h>
31 #include <linux/init.h>
32 #include <linux/delay.h>
33 #include <linux/pm.h>
34 #include <linux/i2c.h>
35 #include <linux/gpio.h>
36 #include <linux/regulator/consumer.h>
37 #include <linux/firmware.h>
38 #include <linux/regmap.h>
39 #include <linux/of.h>
40 #include <linux/of_gpio.h>
41 #include <linux/slab.h>
42 #include <linux/syscalls.h>
43 #include <linux/fcntl.h>
44 #include <asm/uaccess.h>
45 #include <sound/core.h>
46 #include <sound/pcm.h>
47 #include <sound/pcm_params.h>
48 #include <sound/soc.h>
49 #include <sound/initval.h>
50 #include <sound/tlv.h>
52 #include "tas2555-core.h"
53 #include "tas2555-codec.h"
55 #undef KCONTROL_CODEC
57 static unsigned int tas2555_codec_read(struct snd_soc_codec *pCodec,
58         unsigned int nRegister)
59 {
60         struct tas2555_priv *pTAS2555 = snd_soc_codec_get_drvdata(pCodec);
61         int ret = 0;
62         unsigned int Value = 0;
64         ret = pTAS2555->read(pTAS2555, 
65                 pTAS2555->mnCurrentChannel, nRegister, &Value);
66         
67         if (ret < 0) {
68                 dev_err(pTAS2555->dev, "%s, %d, ERROR happen=%d\n", __FUNCTION__,
69                         __LINE__, ret);
70                 return 0;
71         } else
72                 return Value;
73 }
75 static int tas2555_codec_write(struct snd_soc_codec *pCodec, unsigned int nRegister,
76         unsigned int nValue)
77 {
78         struct tas2555_priv *pTAS2555 = snd_soc_codec_get_drvdata(pCodec);
79         int ret = 0;
81         ret = pTAS2555->write(pTAS2555, 
82                 pTAS2555->mnCurrentChannel, nRegister, nValue);
83         
84         return ret;
85 }
87 static const struct snd_soc_dapm_widget tas2555_dapm_widgets[] = {
88         SND_SOC_DAPM_AIF_IN("ASI1", "ASI1 Playback", 0, SND_SOC_NOPM, 0, 0),
89         SND_SOC_DAPM_AIF_IN("ASI2", "ASI2 Playback", 0, SND_SOC_NOPM, 0, 0),
90         SND_SOC_DAPM_AIF_IN("ASIM", "ASIM Playback", 0, SND_SOC_NOPM, 0, 0),
91         SND_SOC_DAPM_DAC("DAC", NULL, SND_SOC_NOPM, 0, 0),
93         SND_SOC_DAPM_OUT_DRV("ClassD", SND_SOC_NOPM, 0, 0, NULL, 0),
95         SND_SOC_DAPM_SUPPLY("PLL", SND_SOC_NOPM, 0, 0, NULL, 0),
96         SND_SOC_DAPM_SUPPLY("NDivider", SND_SOC_NOPM, 0, 0, NULL, 0),
98         SND_SOC_DAPM_OUTPUT("OUT")
99 };
101 static const struct snd_soc_dapm_route tas2555_audio_map[] = {
102         {"DAC", NULL, "ASI1"},
103         {"DAC", NULL, "ASI2"},
104         {"DAC", NULL, "ASIM"},
105         {"ClassD", NULL, "DAC"},
106         {"OUT", NULL, "ClassD"},
107         {"DAC", NULL, "PLL"},
108         {"DAC", NULL, "NDivider"},
109 };
111 static int tas2555_startup(struct snd_pcm_substream *substream,
112         struct snd_soc_dai *dai)
114         struct snd_soc_codec *codec = dai->codec;
115         struct tas2555_priv *pTAS2555 = snd_soc_codec_get_drvdata(codec);
116         
117         dev_dbg(pTAS2555->dev, "%s\n", __func__);
119         return 0;
122 static void tas2555_shutdown(struct snd_pcm_substream *substream,
123         struct snd_soc_dai *dai)
125         struct snd_soc_codec *codec = dai->codec;
126         struct tas2555_priv *pTAS2555 = snd_soc_codec_get_drvdata(codec);
128         dev_dbg(pTAS2555->dev, "%s\n", __func__);
131 static int tas2555_mute(struct snd_soc_dai *dai, int mute)
133         struct snd_soc_codec *codec = dai->codec;
134         struct tas2555_priv *pTAS2555 = snd_soc_codec_get_drvdata(codec);
135         
136         dev_dbg(pTAS2555->dev, "%s\n", __func__);
138         tas2555_enable(pTAS2555, !mute);
139         
140         return 0;
143 static int tas2555_set_dai_sysclk(struct snd_soc_dai *pDAI,
144         int nClkID, unsigned int nFreqency, int nDir)
146         struct snd_soc_codec *pCodec = pDAI->codec;
147         struct tas2555_priv *pTAS2555 = snd_soc_codec_get_drvdata(pCodec);
149         dev_dbg(pTAS2555->dev, "tas2555_set_dai_sysclk: freq = %u\n", nFreqency);
151         return 0;
154 static int tas2555_hw_params(struct snd_pcm_substream *pSubstream,
155         struct snd_pcm_hw_params *pParams, struct snd_soc_dai *pDAI)
157         struct snd_soc_codec *pCodec = pDAI->codec;
158         struct tas2555_priv *pTAS2555 = snd_soc_codec_get_drvdata(pCodec);
160         dev_dbg(pTAS2555->dev, "%s\n", __func__);
161         
162         tas2555_set_bit_rate(pTAS2555, channel_both, 
163                 snd_pcm_format_width(params_format(pParams)));
164         tas2555_set_sampling_rate(pTAS2555, params_rate(pParams));
166         return 0;
169 static int tas2555_set_dai_fmt(struct snd_soc_dai *pDAI, unsigned int nFormat)
171         struct snd_soc_codec *codec = pDAI->codec;
172         struct tas2555_priv *pTAS2555 = snd_soc_codec_get_drvdata(codec);
173         
174         dev_dbg(pTAS2555->dev, "%s\n", __func__);
175         
176         return 0;
179 static int tas2555_prepare(struct snd_pcm_substream *pSubstream,
180         struct snd_soc_dai *pDAI)
182         struct snd_soc_codec *codec = pDAI->codec;
183         struct tas2555_priv *pTAS2555 = snd_soc_codec_get_drvdata(codec);
184         
185         dev_dbg(pTAS2555->dev, "%s\n", __func__);
186         
187         return 0;
190 static int tas2555_set_bias_level(struct snd_soc_codec *pCodec,
191         enum snd_soc_bias_level eLevel)
193         struct tas2555_priv *pTAS2555 = snd_soc_codec_get_drvdata(pCodec);
194         
195         dev_dbg(pTAS2555->dev, "%s: %d\n", __func__, eLevel);
197         return 0;
200 static int tas2555_codec_probe(struct snd_soc_codec *pCodec)
202         struct tas2555_priv *pTAS2555 = snd_soc_codec_get_drvdata(pCodec);
204         dev_dbg(pTAS2555->dev, "%s\n", __func__);
206         return 0;
209 static int tas2555_codec_remove(struct snd_soc_codec *pCodec)
211         return 0;
214 static int tas2555_power_ctrl_get(struct snd_kcontrol *pKcontrol,
215         struct snd_ctl_elem_value *pValue)
217 #ifdef KCONTROL_CODEC
218         struct snd_soc_codec *codec = snd_soc_kcontrol_codec(pKcontrol);
219 #else
220         struct snd_soc_codec *codec = snd_kcontrol_chip(pKcontrol);
221 #endif
222         struct tas2555_priv *pTAS2555 = snd_soc_codec_get_drvdata(codec);
224         pValue->value.integer.value[0] = pTAS2555->mbPowerUp;
225         dev_dbg(pTAS2555->dev, "tas2555_power_ctrl_get = %d\n",
226                 pTAS2555->mbPowerUp);
227                 
228         return 0;
231 static int tas2555_power_ctrl_put(struct snd_kcontrol *pKcontrol,
232         struct snd_ctl_elem_value *pValue)
234 #ifdef KCONTROL_CODEC
235         struct snd_soc_codec *codec = snd_soc_kcontrol_codec(pKcontrol);
236 #else
237         struct snd_soc_codec *codec = snd_kcontrol_chip(pKcontrol);
238 #endif
239         struct tas2555_priv *pTAS2555 = snd_soc_codec_get_drvdata(codec);
241         pTAS2555->mbPowerUp = pValue->value.integer.value[0];
243         dev_dbg(pTAS2555->dev, "tas2555_power_ctrl_put = %d\n",
244                 pTAS2555->mbPowerUp);
246         if (pTAS2555->mbPowerUp == 1)
247                 tas2555_enable(pTAS2555, true);
248         if (pTAS2555->mbPowerUp == 0)
249                 tas2555_enable(pTAS2555, false);
250                 
251         return 0;
254 static int tas2555_fs_get(struct snd_kcontrol *pKcontrol,
255         struct snd_ctl_elem_value *pValue)
257 #ifdef KCONTROL_CODEC
258         struct snd_soc_codec *codec = snd_soc_kcontrol_codec(pKcontrol);
259 #else
260         struct snd_soc_codec *codec = snd_kcontrol_chip(pKcontrol);
261 #endif
262         struct tas2555_priv *pTAS2555 = snd_soc_codec_get_drvdata(codec);
264         int nFS = 48000;
265         
266         if (pTAS2555->mpFirmware->mnConfigurations)
267                 nFS = pTAS2555->mpFirmware->mpConfigurations[pTAS2555->mnCurrentConfiguration].mnSamplingRate;
268         
269         pValue->value.integer.value[0] = nFS;
270                 
271         dev_dbg(pTAS2555->dev, "tas2555_fs_get = %d\n", nFS);
272         return 0;
275 static int tas2555_fs_put(struct snd_kcontrol *pKcontrol,
276         struct snd_ctl_elem_value *pValue)
278 #ifdef KCONTROL_CODEC
279         struct snd_soc_codec *codec = snd_soc_kcontrol_codec(pKcontrol);
280 #else
281         struct snd_soc_codec *codec = snd_kcontrol_chip(pKcontrol);
282 #endif
283         struct tas2555_priv *pTAS2555 = snd_soc_codec_get_drvdata(codec);
284         int ret = 0;
285         int nFS = pValue->value.integer.value[0];
286         
287         dev_info(pTAS2555->dev, "tas2555_fs_put = %d\n", nFS);
288         
289         ret = tas2555_set_sampling_rate(pTAS2555, nFS);
290         
291         return ret;
294 static int tas2555_program_get(struct snd_kcontrol *pKcontrol,
295         struct snd_ctl_elem_value *pValue)
297 #ifdef KCONTROL_CODEC
298         struct snd_soc_codec *codec = snd_soc_kcontrol_codec(pKcontrol);
299 #else
300         struct snd_soc_codec *codec = snd_kcontrol_chip(pKcontrol);
301 #endif
302         struct tas2555_priv *pTAS2555 = snd_soc_codec_get_drvdata(codec);
304         pValue->value.integer.value[0] = pTAS2555->mnCurrentProgram;
305         dev_dbg(pTAS2555->dev, "tas2555_program_get = %d\n",
306                 pTAS2555->mnCurrentProgram);
307                 
308         return 0;
311 static int tas2555_program_put(struct snd_kcontrol *pKcontrol,
312         struct snd_ctl_elem_value *pValue)
314 #ifdef KCONTROL_CODEC
315         struct snd_soc_codec *codec = snd_soc_kcontrol_codec(pKcontrol);
316 #else
317         struct snd_soc_codec *codec = snd_kcontrol_chip(pKcontrol);
318 #endif
319         struct tas2555_priv *pTAS2555 = snd_soc_codec_get_drvdata(codec);
320         unsigned int nProgram = pValue->value.integer.value[0];
321         int ret = 0;
322         
323         ret = tas2555_set_program(pTAS2555, nProgram);
324         
325         return ret;
328 static int tas2555_configuration_get(struct snd_kcontrol *pKcontrol,
329         struct snd_ctl_elem_value *pValue)
331 #ifdef KCONTROL_CODEC
332         struct snd_soc_codec *codec = snd_soc_kcontrol_codec(pKcontrol);
333 #else
334         struct snd_soc_codec *codec = snd_kcontrol_chip(pKcontrol);
335 #endif
336         struct tas2555_priv *pTAS2555 = snd_soc_codec_get_drvdata(codec);
338         pValue->value.integer.value[0] = pTAS2555->mnCurrentConfiguration;
339         dev_dbg(pTAS2555->dev, "tas2555_configuration_get = %d\n",
340                 pTAS2555->mnCurrentConfiguration);
341                         
342         return 0;
345 static int tas2555_configuration_put(struct snd_kcontrol *pKcontrol,
346         struct snd_ctl_elem_value *pValue)
348 #ifdef KCONTROL_CODEC
349         struct snd_soc_codec *codec = snd_soc_kcontrol_codec(pKcontrol);
350 #else
351         struct snd_soc_codec *codec = snd_kcontrol_chip(pKcontrol);
352 #endif
353         struct tas2555_priv *pTAS2555 = snd_soc_codec_get_drvdata(codec);
354         unsigned int nConfiguration = pValue->value.integer.value[0];
355         int ret = 0;
357         ret = tas2555_set_config(pTAS2555, nConfiguration);
358         
359         return ret;
362 static int tas2555_calibration_get(struct snd_kcontrol *pKcontrol,
363         struct snd_ctl_elem_value *pValue)
365 #ifdef KCONTROL_CODEC
366         struct snd_soc_codec *codec = snd_soc_kcontrol_codec(pKcontrol);
367 #else
368         struct snd_soc_codec *codec = snd_kcontrol_chip(pKcontrol);
369 #endif
370         struct tas2555_priv *pTAS2555 = snd_soc_codec_get_drvdata(codec);
372         pValue->value.integer.value[0] = pTAS2555->mnCurrentCalibration;
373         dev_info(pTAS2555->dev,
374                 "tas2555_calibration_get = %d\n",
375                 pTAS2555->mnCurrentCalibration);
376                         
377         return 0;
380 static int tas2555_calibration_put(struct snd_kcontrol *pKcontrol,
381         struct snd_ctl_elem_value *pValue)
383 #ifdef KCONTROL_CODEC
384         struct snd_soc_codec *codec = snd_soc_kcontrol_codec(pKcontrol);
385 #else
386         struct snd_soc_codec *codec = snd_kcontrol_chip(pKcontrol);
387 #endif
388         struct tas2555_priv *pTAS2555 = snd_soc_codec_get_drvdata(codec);
389         unsigned int nCalibration = pValue->value.integer.value[0];
390         int ret = 0;
391         
392         ret = tas2555_set_calibration(pTAS2555, nCalibration);
393         
394         return ret;
397 static int tas2555_ldac_gain_get(struct snd_kcontrol *pKcontrol,
398         struct snd_ctl_elem_value *pValue)
400 #ifdef KCONTROL_CODEC
401         struct snd_soc_codec *codec = snd_soc_kcontrol_codec(pKcontrol);
402 #else
403         struct snd_soc_codec *codec = snd_kcontrol_chip(pKcontrol);
404 #endif
405         struct tas2555_priv *pTAS2555 = snd_soc_codec_get_drvdata(codec);
406         unsigned char nGain = 0;
407         int ret = -1;
408         
409         ret = tas2555_get_DAC_gain(pTAS2555, channel_left, &nGain);
410         if(ret >= 0){
411                 pValue->value.integer.value[0] = nGain;
412         }
413         
414         dev_dbg(pTAS2555->dev, "%s, ret = %d, %d\n", __func__, ret, nGain);
415                         
416         return ret;
419 static int tas2555_ldac_gain_put(struct snd_kcontrol *pKcontrol,
420         struct snd_ctl_elem_value *pValue)
422 #ifdef KCONTROL_CODEC
423         struct snd_soc_codec *codec = snd_soc_kcontrol_codec(pKcontrol);
424 #else
425         struct snd_soc_codec *codec = snd_kcontrol_chip(pKcontrol);
426 #endif
427         struct tas2555_priv *pTAS2555 = snd_soc_codec_get_drvdata(codec);
428         unsigned int nGain = pValue->value.integer.value[0];
429         int ret = 0;
430         
431         ret = tas2555_set_DAC_gain(pTAS2555, channel_left, nGain);
432         
433         return ret;
436 static int tas2555_rdac_gain_get(struct snd_kcontrol *pKcontrol,
437         struct snd_ctl_elem_value *pValue)
439 #ifdef KCONTROL_CODEC
440         struct snd_soc_codec *codec = snd_soc_kcontrol_codec(pKcontrol);
441 #else
442         struct snd_soc_codec *codec = snd_kcontrol_chip(pKcontrol);
443 #endif
444         struct tas2555_priv *pTAS2555 = snd_soc_codec_get_drvdata(codec);
445         unsigned char nGain = 0;
446         int ret = -1;
447         
448         ret = tas2555_get_DAC_gain(pTAS2555, channel_right, &nGain);
449         if(ret >= 0){
450                 pValue->value.integer.value[0] = nGain;
451         }
452         
453         dev_dbg(pTAS2555->dev, "%s, ret = %d, %d\n", __func__, ret, nGain);
454                         
455         return ret;
458 static int tas2555_rdac_gain_put(struct snd_kcontrol *pKcontrol,
459         struct snd_ctl_elem_value *pValue)
461 #ifdef KCONTROL_CODEC
462         struct snd_soc_codec *codec = snd_soc_kcontrol_codec(pKcontrol);
463 #else
464         struct snd_soc_codec *codec = snd_kcontrol_chip(pKcontrol);
465 #endif
466         struct tas2555_priv *pTAS2555 = snd_soc_codec_get_drvdata(codec);
467         unsigned int nGain = pValue->value.integer.value[0];
468         int ret = 0;
469         
470         ret = tas2555_set_DAC_gain(pTAS2555, channel_right, nGain);
471         
472         return ret;
475 static const struct snd_kcontrol_new tas2555_snd_controls[] = {
476         SOC_SINGLE_EXT("LDAC Playback Volume", SND_SOC_NOPM, 0, 0x0f, 0, 
477                 tas2555_ldac_gain_get, tas2555_ldac_gain_put),
478         SOC_SINGLE_EXT("RDAC Playback Volume", SND_SOC_NOPM, 0, 0x0f, 0, 
479                 tas2555_rdac_gain_get, tas2555_rdac_gain_put),          
480         SOC_SINGLE_EXT("PowerCtrl", SND_SOC_NOPM, 0, 0x0001, 0,
481                 tas2555_power_ctrl_get, tas2555_power_ctrl_put),
482         SOC_SINGLE_EXT("Program", SND_SOC_NOPM, 0, 0x00FF, 0, tas2555_program_get,
483                 tas2555_program_put),
484         SOC_SINGLE_EXT("Configuration", SND_SOC_NOPM, 0, 0x00FF, 0,
485                 tas2555_configuration_get, tas2555_configuration_put),
486         SOC_SINGLE_EXT("FS", SND_SOC_NOPM, 8000, 48000, 0,
487                 tas2555_fs_get, tas2555_fs_put),
488         SOC_SINGLE_EXT("Calibration", SND_SOC_NOPM, 0, 0x00FF, 0,
489                 tas2555_calibration_get, tas2555_calibration_put),
490 };
492 static struct snd_soc_codec_driver soc_codec_driver_tas2555 = {
493         .probe = tas2555_codec_probe,
494         .remove = tas2555_codec_remove,
495         .read = tas2555_codec_read,
496         .write = tas2555_codec_write,
497         .set_bias_level = tas2555_set_bias_level,
498         .idle_bias_off = true,
499         //.ignore_pmdown_time = true,
500         .controls = tas2555_snd_controls,
501         .num_controls = ARRAY_SIZE(tas2555_snd_controls),
502         .dapm_widgets = tas2555_dapm_widgets,
503         .num_dapm_widgets = ARRAY_SIZE(tas2555_dapm_widgets),
504         .dapm_routes = tas2555_audio_map,
505         .num_dapm_routes = ARRAY_SIZE(tas2555_audio_map),
506 };
508 static struct snd_soc_dai_ops tas2555_dai_ops = {
509         .startup = tas2555_startup,
510         .shutdown = tas2555_shutdown,
511         .digital_mute = tas2555_mute,
512         .hw_params = tas2555_hw_params,
513         .prepare = tas2555_prepare,
514         .set_sysclk = tas2555_set_dai_sysclk,
515         .set_fmt = tas2555_set_dai_fmt,
516 };
518 #define TAS2555_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
519              SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
520 static struct snd_soc_dai_driver tas2555_dai_driver[] = {
521         {
522                 .name = "tas2555 ASI1",
523                 .id = 0,
524                 .playback = {
525                                 .stream_name = "ASI1 Playback",
526                                 .channels_min = 2,
527                                 .channels_max = 2,
528                                 .rates = SNDRV_PCM_RATE_8000_192000,
529                                 .formats = TAS2555_FORMATS,
530                         },
531                 .ops = &tas2555_dai_ops,
532                 .symmetric_rates = 1,
533         },
534         {
535                 .name = "tas2555 ASI2",
536                 .id = 1,
537                 .playback = {
538                                 .stream_name = "ASI2 Playback",
539                                 .channels_min = 2,
540                                 .channels_max = 2,
541                                 .rates = SNDRV_PCM_RATE_8000_192000,
542                                 .formats = TAS2555_FORMATS,
543                         },
544                 .ops = &tas2555_dai_ops,
545                 .symmetric_rates = 1,
546         },
547         {
548                 .name = "tas2555 ASIM",
549                 .id = 2,
550                 .playback = {
551                                 .stream_name = "ASIM Playback",
552                                 .channels_min = 2,
553                                 .channels_max = 2,
554                                 .rates = SNDRV_PCM_RATE_8000_192000,
555                                 .formats = TAS2555_FORMATS,
556                         },
557                 .ops = &tas2555_dai_ops,
558                 .symmetric_rates = 1,
559         },
560 };
562 int tas2555_register_codec(struct tas2555_priv *pTAS2555)
564         int nResult = 0;
566         dev_info(pTAS2555->dev, "%s, enter\n", __FUNCTION__);
567           
568         nResult = snd_soc_register_codec(pTAS2555->dev, 
569                 &soc_codec_driver_tas2555,
570                 tas2555_dai_driver, ARRAY_SIZE(tas2555_dai_driver));
571                 
572         return nResult;
575 int tas2555_deregister_codec(struct tas2555_priv *pTAS2555)
577         snd_soc_unregister_codec(pTAS2555->dev);
578                 
579         return 0;
582 MODULE_AUTHOR("Texas Instruments Inc.");
583 MODULE_DESCRIPTION("TAS2555 ALSA SOC Smart Amplifier driver");
584 MODULE_LICENSE("GPLv2");
585 #endif