2bd6fb462d2075703ff628dbbc488fb06b40db73
[tas2557sw-android/tas2557-android-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
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, nRegister, &Value);
63         if (ret < 0)
64                 dev_err(pTAS2557->dev, "%s, %d, ERROR happen=%d\n", __func__,
65                         __LINE__, ret);
66         else
67                 ret = Value;
69         mutex_unlock(&pTAS2557->codec_lock);
70         return ret;
71 }
73 static int tas2557_codec_write(struct snd_soc_codec *pCodec, unsigned int nRegister,
74         unsigned int nValue)
75 {
76         struct tas2557_priv *pTAS2557 = snd_soc_codec_get_drvdata(pCodec);
77         int ret = 0;
79         mutex_lock(&pTAS2557->codec_lock);
81         ret = pTAS2557->write(pTAS2557, nRegister, nValue);
83         mutex_unlock(&pTAS2557->codec_lock);
84         return ret;
85 }
87 static const struct snd_soc_dapm_widget tas2557_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 tas2557_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 tas2557_startup(struct snd_pcm_substream *substream,
112         struct snd_soc_dai *dai)
114         struct snd_soc_codec *codec = dai->codec;
115         struct tas2557_priv *pTAS2557 = snd_soc_codec_get_drvdata(codec);
117         dev_dbg(pTAS2557->dev, "%s\n", __func__);
118         return 0;
121 static void tas2557_shutdown(struct snd_pcm_substream *substream,
122         struct snd_soc_dai *dai)
124         struct snd_soc_codec *codec = dai->codec;
125         struct tas2557_priv *pTAS2557 = snd_soc_codec_get_drvdata(codec);
127         dev_dbg(pTAS2557->dev, "%s\n", __func__);
130 static int tas2557_mute(struct snd_soc_dai *dai, int mute)
132         struct snd_soc_codec *codec = dai->codec;
133         struct tas2557_priv *pTAS2557 = snd_soc_codec_get_drvdata(codec);
135         mutex_lock(&pTAS2557->codec_lock);
137         dev_dbg(pTAS2557->dev, "%s\n", __func__);
138         tas2557_enable(pTAS2557, !mute);
140         mutex_unlock(&pTAS2557->codec_lock);
141         return 0;
144 static int tas2557_set_dai_sysclk(struct snd_soc_dai *pDAI,
145         int nClkID, unsigned int nFreqency, int nDir)
147         struct snd_soc_codec *pCodec = pDAI->codec;
148         struct tas2557_priv *pTAS2557 = snd_soc_codec_get_drvdata(pCodec);
150         dev_dbg(pTAS2557->dev, "tas2557_set_dai_sysclk: freq = %u\n", nFreqency);
152         return 0;
155 static int tas2557_hw_params(struct snd_pcm_substream *pSubstream,
156         struct snd_pcm_hw_params *pParams, struct snd_soc_dai *pDAI)
158         struct snd_soc_codec *pCodec = pDAI->codec;
159         struct tas2557_priv *pTAS2557 = snd_soc_codec_get_drvdata(pCodec);
161         mutex_lock(&pTAS2557->codec_lock);
163         dev_dbg(pTAS2557->dev, "%s\n", __func__);
164 /* do bit rate setting during platform data */
165 /* tas2557_set_bit_rate(pTAS2557, channel_both, snd_pcm_format_width(params_format(pParams))); */
166         tas2557_set_sampling_rate(pTAS2557, params_rate(pParams));
168         mutex_unlock(&pTAS2557->codec_lock);
169         return 0;
172 static int tas2557_set_dai_fmt(struct snd_soc_dai *pDAI, unsigned int nFormat)
174         struct snd_soc_codec *codec = pDAI->codec;
175         struct tas2557_priv *pTAS2557 = snd_soc_codec_get_drvdata(codec);
177         dev_dbg(pTAS2557->dev, "%s\n", __func__);
178         return 0;
181 static int tas2557_prepare(struct snd_pcm_substream *pSubstream,
182         struct snd_soc_dai *pDAI)
184         struct snd_soc_codec *codec = pDAI->codec;
185         struct tas2557_priv *pTAS2557 = snd_soc_codec_get_drvdata(codec);
187         dev_dbg(pTAS2557->dev, "%s\n", __func__);
188         return 0;
191 static int tas2557_set_bias_level(struct snd_soc_codec *pCodec,
192         enum snd_soc_bias_level eLevel)
194         struct tas2557_priv *pTAS2557 = snd_soc_codec_get_drvdata(pCodec);
196         dev_dbg(pTAS2557->dev, "%s: %d\n", __func__, eLevel);
197         return 0;
200 static int tas2557_codec_probe(struct snd_soc_codec *pCodec)
202         struct tas2557_priv *pTAS2557 = snd_soc_codec_get_drvdata(pCodec);
204         dev_dbg(pTAS2557->dev, "%s\n", __func__);
205         return 0;
208 static int tas2557_codec_remove(struct snd_soc_codec *pCodec)
210         return 0;
213 static int tas2557_power_ctrl_get(struct snd_kcontrol *pKcontrol,
214         struct snd_ctl_elem_value *pValue)
216 #ifdef KCONTROL_CODEC
217         struct snd_soc_codec *codec = snd_soc_kcontrol_codec(pKcontrol);
218 #else
219         struct snd_soc_codec *codec = snd_kcontrol_chip(pKcontrol);
220 #endif
221         struct tas2557_priv *pTAS2557 = snd_soc_codec_get_drvdata(codec);
223         mutex_lock(&pTAS2557->codec_lock);
225         pValue->value.integer.value[0] = pTAS2557->mbPowerUp;
226         dev_dbg(pTAS2557->dev, "tas2557_power_ctrl_get = %d\n",
227                 pTAS2557->mbPowerUp);
229         mutex_unlock(&pTAS2557->codec_lock);
230         return 0;
233 static int tas2557_power_ctrl_put(struct snd_kcontrol *pKcontrol,
234         struct snd_ctl_elem_value *pValue)
236 #ifdef KCONTROL_CODEC
237         struct snd_soc_codec *codec = snd_soc_kcontrol_codec(pKcontrol);
238 #else
239         struct snd_soc_codec *codec = snd_kcontrol_chip(pKcontrol);
240 #endif
241         struct tas2557_priv *pTAS2557 = snd_soc_codec_get_drvdata(codec);
243         int nPowerOn = pValue->value.integer.value[0];
245         mutex_lock(&pTAS2557->codec_lock);
247         dev_dbg(pTAS2557->dev, "tas2557_power_ctrl_put = %d\n", nPowerOn);
248         tas2557_enable(pTAS2557, (nPowerOn != 0));
250         mutex_unlock(&pTAS2557->codec_lock);
251         return 0;
254 static int tas2557_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 tas2557_priv *pTAS2557 = snd_soc_codec_get_drvdata(codec);
263         int nFS = 48000;
265         mutex_lock(&pTAS2557->codec_lock);
267         if (pTAS2557->mpFirmware->mnConfigurations)
268                 nFS = pTAS2557->mpFirmware->mpConfigurations[pTAS2557->mnCurrentConfiguration].mnSamplingRate;
269         pValue->value.integer.value[0] = nFS;
270         dev_dbg(pTAS2557->dev, "tas2557_fs_get = %d\n", nFS);
272         mutex_unlock(&pTAS2557->codec_lock);
273         return 0;
276 static int tas2557_fs_put(struct snd_kcontrol *pKcontrol,
277         struct snd_ctl_elem_value *pValue)
279 #ifdef KCONTROL_CODEC
280         struct snd_soc_codec *codec = snd_soc_kcontrol_codec(pKcontrol);
281 #else
282         struct snd_soc_codec *codec = snd_kcontrol_chip(pKcontrol);
283 #endif
284         struct tas2557_priv *pTAS2557 = snd_soc_codec_get_drvdata(codec);
285         int ret = 0;
286         int nFS = pValue->value.integer.value[0];
288         mutex_lock(&pTAS2557->codec_lock);
290         dev_info(pTAS2557->dev, "tas2557_fs_put = %d\n", nFS);
291         ret = tas2557_set_sampling_rate(pTAS2557, nFS);
293         mutex_unlock(&pTAS2557->codec_lock);
294         return ret;
297 static int tas2557_program_get(struct snd_kcontrol *pKcontrol,
298         struct snd_ctl_elem_value *pValue)
300 #ifdef KCONTROL_CODEC
301         struct snd_soc_codec *codec = snd_soc_kcontrol_codec(pKcontrol);
302 #else
303         struct snd_soc_codec *codec = snd_kcontrol_chip(pKcontrol);
304 #endif
305         struct tas2557_priv *pTAS2557 = snd_soc_codec_get_drvdata(codec);
307         mutex_lock(&pTAS2557->codec_lock);
309         pValue->value.integer.value[0] = pTAS2557->mnCurrentProgram;
310         dev_dbg(pTAS2557->dev, "tas2557_program_get = %d\n",
311                 pTAS2557->mnCurrentProgram);
313         mutex_unlock(&pTAS2557->codec_lock);
314         return 0;
317 static int tas2557_program_put(struct snd_kcontrol *pKcontrol,
318         struct snd_ctl_elem_value *pValue)
320 #ifdef KCONTROL_CODEC
321         struct snd_soc_codec *codec = snd_soc_kcontrol_codec(pKcontrol);
322 #else
323         struct snd_soc_codec *codec = snd_kcontrol_chip(pKcontrol);
324 #endif
325         struct tas2557_priv *pTAS2557 = snd_soc_codec_get_drvdata(codec);
326         unsigned int nProgram = pValue->value.integer.value[0];
327         int ret = 0;
329         mutex_lock(&pTAS2557->codec_lock);
331         ret = tas2557_set_program(pTAS2557, nProgram, -1);
333         mutex_unlock(&pTAS2557->codec_lock);
334         return ret;
337 static int tas2557_configuration_get(struct snd_kcontrol *pKcontrol,
338         struct snd_ctl_elem_value *pValue)
340 #ifdef KCONTROL_CODEC
341         struct snd_soc_codec *codec = snd_soc_kcontrol_codec(pKcontrol);
342 #else
343         struct snd_soc_codec *codec = snd_kcontrol_chip(pKcontrol);
344 #endif
345         struct tas2557_priv *pTAS2557 = snd_soc_codec_get_drvdata(codec);
347         mutex_lock(&pTAS2557->codec_lock);
349         pValue->value.integer.value[0] = pTAS2557->mnCurrentConfiguration;
350         dev_dbg(pTAS2557->dev, "tas2557_configuration_get = %d\n",
351                 pTAS2557->mnCurrentConfiguration);
353         mutex_unlock(&pTAS2557->codec_lock);
354         return 0;
357 static int tas2557_configuration_put(struct snd_kcontrol *pKcontrol,
358         struct snd_ctl_elem_value *pValue)
360 #ifdef KCONTROL_CODEC
361         struct snd_soc_codec *codec = snd_soc_kcontrol_codec(pKcontrol);
362 #else
363         struct snd_soc_codec *codec = snd_kcontrol_chip(pKcontrol);
364 #endif
365         struct tas2557_priv *pTAS2557 = snd_soc_codec_get_drvdata(codec);
366         unsigned int nConfiguration = pValue->value.integer.value[0];
367         int ret = 0;
369         mutex_lock(&pTAS2557->codec_lock);
371         dev_info(pTAS2557->dev, "%s = %d\n", __func__, nConfiguration);
372         ret = tas2557_set_config(pTAS2557, nConfiguration);
374         mutex_unlock(&pTAS2557->codec_lock);
375         return ret;
378 static int tas2557_calibration_get(struct snd_kcontrol *pKcontrol,
379         struct snd_ctl_elem_value *pValue)
381 #ifdef KCONTROL_CODEC
382         struct snd_soc_codec *codec = snd_soc_kcontrol_codec(pKcontrol);
383 #else
384         struct snd_soc_codec *codec = snd_kcontrol_chip(pKcontrol);
385 #endif
386         struct tas2557_priv *pTAS2557 = snd_soc_codec_get_drvdata(codec);
388         mutex_lock(&pTAS2557->codec_lock);
390         pValue->value.integer.value[0] = pTAS2557->mnCurrentCalibration;
391         dev_info(pTAS2557->dev,
392                 "tas2557_calibration_get = %d\n",
393                 pTAS2557->mnCurrentCalibration);
395         mutex_unlock(&pTAS2557->codec_lock);
396         return 0;
399 static int tas2557_calibration_put(struct snd_kcontrol *pKcontrol,
400         struct snd_ctl_elem_value *pValue)
402 #ifdef KCONTROL_CODEC
403         struct snd_soc_codec *codec = snd_soc_kcontrol_codec(pKcontrol);
404 #else
405         struct snd_soc_codec *codec = snd_kcontrol_chip(pKcontrol);
406 #endif
407         struct tas2557_priv *pTAS2557 = snd_soc_codec_get_drvdata(codec);
408         unsigned int nCalibration = pValue->value.integer.value[0];
409         int ret = 0;
411         mutex_lock(&pTAS2557->codec_lock);
413         ret = tas2557_set_calibration(pTAS2557, nCalibration);
415         mutex_unlock(&pTAS2557->codec_lock);
416         return ret;
420 /*
421  * DAC digital volumes. From 0 to 15 dB in 1 dB steps
422  */
423 static DECLARE_TLV_DB_SCALE(dac_tlv, 0, 100, 0);
427         
429 static const char * const chl_setup_text[] = {
430         "default",
431         "DevA-Mute",
432         "DevA-Left",
433         "DevA-Right",
434         "DevA-MonoMix"
435 };
436 static const struct soc_enum chl_setup_enum[] = {
437         SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(chl_setup_text), chl_setup_text),
438 };
440 static int tas2557_dsp_chl_setup_get(struct snd_kcontrol *pKcontrol,
441                         struct snd_ctl_elem_value *pValue)
443 #ifdef KCONTROL_CODEC
444         struct snd_soc_codec *codec = snd_soc_kcontrol_codec(pKcontrol);
445 #else
446         struct snd_soc_codec *codec = snd_kcontrol_chip(pKcontrol);
447 #endif
448         struct tas2557_priv *pTAS2557 = snd_soc_codec_get_drvdata(codec);
450         mutex_lock(&pTAS2557->codec_lock);
452         pValue->value.integer.value[0] = pTAS2557->mnChannelState;
454         mutex_unlock(&pTAS2557->codec_lock);
456         return 0;
459 static int tas2557_dsp_chl_setup_put(struct snd_kcontrol *pKcontrol,
460                         struct snd_ctl_elem_value *pValue)
462 #ifdef KCONTROL_CODEC
463         struct snd_soc_codec *codec = snd_soc_kcontrol_codec(pKcontrol);
464 #else
465         struct snd_soc_codec *codec = snd_kcontrol_chip(pKcontrol);
466 #endif
467         struct tas2557_priv *pTAS2557 = snd_soc_codec_get_drvdata(codec);
468         int channel_state = pValue->value.integer.value[0];
470         mutex_lock(&pTAS2557->codec_lock);
472         tas2557_SA_DevChnSetup(pTAS2557, channel_state);
474         mutex_unlock(&pTAS2557->codec_lock);
475         return 0;
478 static const struct snd_kcontrol_new tas2557_snd_controls[] = {
479         SOC_SINGLE_TLV("DAC Playback Volume", TAS2557_SPK_CTRL_REG, 3, 0x0f, 0,
480                 dac_tlv),
481         SOC_SINGLE_EXT("PowerCtrl", SND_SOC_NOPM, 0, 0x0001, 0,
482                 tas2557_power_ctrl_get, tas2557_power_ctrl_put),
483         SOC_SINGLE_EXT("Program", SND_SOC_NOPM, 0, 0x00FF, 0, tas2557_program_get,
484                 tas2557_program_put),
485         SOC_SINGLE_EXT("Configuration", SND_SOC_NOPM, 0, 0x00FF, 0,
486                 tas2557_configuration_get, tas2557_configuration_put),
487         SOC_SINGLE_EXT("FS", SND_SOC_NOPM, 8000, 48000, 0,
488                 tas2557_fs_get, tas2557_fs_put),
489         SOC_SINGLE_EXT("Calibration", SND_SOC_NOPM, 0, 0x00FF, 0,
490                 tas2557_calibration_get, tas2557_calibration_put),
491         SOC_ENUM_EXT("DSPChl Setup", chl_setup_enum[0],
492                 tas2557_dsp_chl_setup_get, tas2557_dsp_chl_setup_put),
493 };
495 static struct snd_soc_codec_driver soc_codec_driver_tas2557 = {
496         .probe = tas2557_codec_probe,
497         .remove = tas2557_codec_remove,
498         .read = tas2557_codec_read,
499         .write = tas2557_codec_write,
500         .set_bias_level = tas2557_set_bias_level,
501         .idle_bias_off = true,
502         .controls = tas2557_snd_controls,
503         .num_controls = ARRAY_SIZE(tas2557_snd_controls),
504         .dapm_widgets = tas2557_dapm_widgets,
505         .num_dapm_widgets = ARRAY_SIZE(tas2557_dapm_widgets),
506         .dapm_routes = tas2557_audio_map,
507         .num_dapm_routes = ARRAY_SIZE(tas2557_audio_map),
508 };
510 static struct snd_soc_dai_ops tas2557_dai_ops = {
511         .startup = tas2557_startup,
512         .shutdown = tas2557_shutdown,
513         .digital_mute = tas2557_mute,
514         .hw_params = tas2557_hw_params,
515         .prepare = tas2557_prepare,
516         .set_sysclk = tas2557_set_dai_sysclk,
517         .set_fmt = tas2557_set_dai_fmt,
518 };
520 #define TAS2557_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
521         SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
522 static struct snd_soc_dai_driver tas2557_dai_driver[] = {
523         {
524                 .name = "tas2557 ASI1",
525                 .id = 0,
526                 .playback = {
527                                 .stream_name = "ASI1 Playback",
528                                 .channels_min = 2,
529                                 .channels_max = 2,
530                                 .rates = SNDRV_PCM_RATE_8000_192000,
531                                 .formats = TAS2557_FORMATS,
532                         },
533                 .ops = &tas2557_dai_ops,
534                 .symmetric_rates = 1,
535         },
536         {
537                 .name = "tas2557 ASI2",
538                 .id = 1,
539                 .playback = {
540                                 .stream_name = "ASI2 Playback",
541                                 .channels_min = 2,
542                                 .channels_max = 2,
543                                 .rates = SNDRV_PCM_RATE_8000_192000,
544                                 .formats = TAS2557_FORMATS,
545                         },
546                 .ops = &tas2557_dai_ops,
547                 .symmetric_rates = 1,
548         },
549         {
550                 .name = "tas2557 ASIM",
551                 .id = 2,
552                 .playback = {
553                                 .stream_name = "ASIM Playback",
554                                 .channels_min = 2,
555                                 .channels_max = 2,
556                                 .rates = SNDRV_PCM_RATE_8000_192000,
557                                 .formats = TAS2557_FORMATS,
558                         },
559                 .ops = &tas2557_dai_ops,
560                 .symmetric_rates = 1,
561         },
562 };
564 int tas2557_register_codec(struct tas2557_priv *pTAS2557)
566         int nResult = 0;
568         dev_info(pTAS2557->dev, "%s, enter\n", __func__);
569         nResult = snd_soc_register_codec(pTAS2557->dev,
570                 &soc_codec_driver_tas2557,
571                 tas2557_dai_driver, ARRAY_SIZE(tas2557_dai_driver));
572         return nResult;
575 int tas2557_deregister_codec(struct tas2557_priv *pTAS2557)
577         snd_soc_unregister_codec(pTAS2557->dev);
578         return 0;
581 MODULE_AUTHOR("Texas Instruments Inc.");
582 MODULE_DESCRIPTION("TAS2557 ALSA SOC Smart Amplifier driver");
583 MODULE_LICENSE("GPL v2");
584 #endif