update: clock error detection, calibration_re reading,
[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_Cali_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);
306         int ret = 0;
307         int prm_r0 = 0;
309         mutex_lock(&pTAS2557->codec_lock);
311         ret = tas2557_get_Cali_prm_r0(pTAS2557, &prm_r0);
312         pValue->value.integer.value[0] = prm_r0;
313         dev_dbg(pTAS2557->dev, "%s = 0x%x\n", __func__, prm_r0);
315         mutex_unlock(&pTAS2557->codec_lock);
316         return ret;
318 static int tas2557_program_get(struct snd_kcontrol *pKcontrol,
319         struct snd_ctl_elem_value *pValue)
321 #ifdef KCONTROL_CODEC
322         struct snd_soc_codec *codec = snd_soc_kcontrol_codec(pKcontrol);
323 #else
324         struct snd_soc_codec *codec = snd_kcontrol_chip(pKcontrol);
325 #endif
326         struct tas2557_priv *pTAS2557 = snd_soc_codec_get_drvdata(codec);
328         mutex_lock(&pTAS2557->codec_lock);
330         pValue->value.integer.value[0] = pTAS2557->mnCurrentProgram;
331         dev_dbg(pTAS2557->dev, "tas2557_program_get = %d\n",
332                 pTAS2557->mnCurrentProgram);
334         mutex_unlock(&pTAS2557->codec_lock);
335         return 0;
338 static int tas2557_program_put(struct snd_kcontrol *pKcontrol,
339         struct snd_ctl_elem_value *pValue)
341 #ifdef KCONTROL_CODEC
342         struct snd_soc_codec *codec = snd_soc_kcontrol_codec(pKcontrol);
343 #else
344         struct snd_soc_codec *codec = snd_kcontrol_chip(pKcontrol);
345 #endif
346         struct tas2557_priv *pTAS2557 = snd_soc_codec_get_drvdata(codec);
347         unsigned int nProgram = pValue->value.integer.value[0];
348         int ret = 0, nConfiguration = -1;
350         mutex_lock(&pTAS2557->codec_lock);
352         if (nProgram == pTAS2557->mnCurrentProgram)
353                 nConfiguration = pTAS2557->mnCurrentConfiguration;
354         ret = tas2557_set_program(pTAS2557, nProgram, nConfiguration);
356         mutex_unlock(&pTAS2557->codec_lock);
357         return ret;
360 static int tas2557_configuration_get(struct snd_kcontrol *pKcontrol,
361         struct snd_ctl_elem_value *pValue)
363 #ifdef KCONTROL_CODEC
364         struct snd_soc_codec *codec = snd_soc_kcontrol_codec(pKcontrol);
365 #else
366         struct snd_soc_codec *codec = snd_kcontrol_chip(pKcontrol);
367 #endif
368         struct tas2557_priv *pTAS2557 = snd_soc_codec_get_drvdata(codec);
370         mutex_lock(&pTAS2557->codec_lock);
372         pValue->value.integer.value[0] = pTAS2557->mnCurrentConfiguration;
373         dev_dbg(pTAS2557->dev, "tas2557_configuration_get = %d\n",
374                 pTAS2557->mnCurrentConfiguration);
376         mutex_unlock(&pTAS2557->codec_lock);
377         return 0;
380 static int tas2557_configuration_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 tas2557_priv *pTAS2557 = snd_soc_codec_get_drvdata(codec);
389         unsigned int nConfiguration = pValue->value.integer.value[0];
390         int ret = 0;
392         mutex_lock(&pTAS2557->codec_lock);
394         dev_info(pTAS2557->dev, "%s = %d\n", __func__, nConfiguration);
395         ret = tas2557_set_config(pTAS2557, nConfiguration);
397         mutex_unlock(&pTAS2557->codec_lock);
398         return ret;
401 static int tas2557_calibration_get(struct snd_kcontrol *pKcontrol,
402         struct snd_ctl_elem_value *pValue)
404 #ifdef KCONTROL_CODEC
405         struct snd_soc_codec *codec = snd_soc_kcontrol_codec(pKcontrol);
406 #else
407         struct snd_soc_codec *codec = snd_kcontrol_chip(pKcontrol);
408 #endif
409         struct tas2557_priv *pTAS2557 = snd_soc_codec_get_drvdata(codec);
411         mutex_lock(&pTAS2557->codec_lock);
413         pValue->value.integer.value[0] = pTAS2557->mnCurrentCalibration;
414         dev_info(pTAS2557->dev,
415                 "tas2557_calibration_get = %d\n",
416                 pTAS2557->mnCurrentCalibration);
418         mutex_unlock(&pTAS2557->codec_lock);
419         return 0;
422 static int tas2557_calibration_put(struct snd_kcontrol *pKcontrol,
423         struct snd_ctl_elem_value *pValue)
425 #ifdef KCONTROL_CODEC
426         struct snd_soc_codec *codec = snd_soc_kcontrol_codec(pKcontrol);
427 #else
428         struct snd_soc_codec *codec = snd_kcontrol_chip(pKcontrol);
429 #endif
430         struct tas2557_priv *pTAS2557 = snd_soc_codec_get_drvdata(codec);
431         unsigned int nCalibration = pValue->value.integer.value[0];
432         int ret = 0;
434         mutex_lock(&pTAS2557->codec_lock);
436         ret = tas2557_set_calibration(pTAS2557, nCalibration);
438         mutex_unlock(&pTAS2557->codec_lock);
439         return ret;
442 static const struct snd_kcontrol_new tas2557_snd_controls[] = {
443         SOC_SINGLE_EXT("PowerCtrl", SND_SOC_NOPM, 0, 0x0001, 0,
444                 tas2557_power_ctrl_get, tas2557_power_ctrl_put),
445         SOC_SINGLE_EXT("Program", SND_SOC_NOPM, 0, 0x00FF, 0, tas2557_program_get,
446                 tas2557_program_put),
447         SOC_SINGLE_EXT("Configuration", SND_SOC_NOPM, 0, 0x00FF, 0,
448                 tas2557_configuration_get, tas2557_configuration_put),
449         SOC_SINGLE_EXT("FS", SND_SOC_NOPM, 8000, 48000, 0,
450                 tas2557_fs_get, tas2557_fs_put),
451         SOC_SINGLE_EXT("Get Cali_Re", SND_SOC_NOPM, 0, 0x7f000000, 0,
452                 tas2557_Cali_get, NULL),
453         SOC_SINGLE_EXT("Calibration", SND_SOC_NOPM, 0, 0x00FF, 0,
454                 tas2557_calibration_get, tas2557_calibration_put),
455 };
457 static struct snd_soc_codec_driver soc_codec_driver_tas2557 = {
458         .probe = tas2557_codec_probe,
459         .remove = tas2557_codec_remove,
460         .read = tas2557_codec_read,
461         .write = tas2557_codec_write,
462         .set_bias_level = tas2557_set_bias_level,
463         .idle_bias_off = true,
464         .controls = tas2557_snd_controls,
465         .num_controls = ARRAY_SIZE(tas2557_snd_controls),
466         .dapm_widgets = tas2557_dapm_widgets,
467         .num_dapm_widgets = ARRAY_SIZE(tas2557_dapm_widgets),
468         .dapm_routes = tas2557_audio_map,
469         .num_dapm_routes = ARRAY_SIZE(tas2557_audio_map),
470 };
472 static struct snd_soc_dai_ops tas2557_dai_ops = {
473         .startup = tas2557_startup,
474         .shutdown = tas2557_shutdown,
475         .digital_mute = tas2557_mute,
476         .hw_params = tas2557_hw_params,
477         .prepare = tas2557_prepare,
478         .set_sysclk = tas2557_set_dai_sysclk,
479         .set_fmt = tas2557_set_dai_fmt,
480 };
482 #define TAS2557_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
483         SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
484 static struct snd_soc_dai_driver tas2557_dai_driver[] = {
485         {
486                 .name = "tas2557 ASI1",
487                 .id = 0,
488                 .playback = {
489                                 .stream_name = "ASI1 Playback",
490                                 .channels_min = 2,
491                                 .channels_max = 2,
492                                 .rates = SNDRV_PCM_RATE_8000_192000,
493                                 .formats = TAS2557_FORMATS,
494                         },
495                 .ops = &tas2557_dai_ops,
496                 .symmetric_rates = 1,
497         },
498         {
499                 .name = "tas2557 ASI2",
500                 .id = 1,
501                 .playback = {
502                                 .stream_name = "ASI2 Playback",
503                                 .channels_min = 2,
504                                 .channels_max = 2,
505                                 .rates = SNDRV_PCM_RATE_8000_192000,
506                                 .formats = TAS2557_FORMATS,
507                         },
508                 .ops = &tas2557_dai_ops,
509                 .symmetric_rates = 1,
510         },
511         {
512                 .name = "tas2557 ASIM",
513                 .id = 2,
514                 .playback = {
515                                 .stream_name = "ASIM Playback",
516                                 .channels_min = 2,
517                                 .channels_max = 2,
518                                 .rates = SNDRV_PCM_RATE_8000_192000,
519                                 .formats = TAS2557_FORMATS,
520                         },
521                 .ops = &tas2557_dai_ops,
522                 .symmetric_rates = 1,
523         },
524 };
526 int tas2557_register_codec(struct tas2557_priv *pTAS2557)
528         int nResult = 0;
530         dev_info(pTAS2557->dev, "%s, enter\n", __func__);
531         nResult = snd_soc_register_codec(pTAS2557->dev,
532                 &soc_codec_driver_tas2557,
533                 tas2557_dai_driver, ARRAY_SIZE(tas2557_dai_driver));
534         return nResult;
537 int tas2557_deregister_codec(struct tas2557_priv *pTAS2557)
539         snd_soc_unregister_codec(pTAS2557->dev);
540         return 0;
543 MODULE_AUTHOR("Texas Instruments Inc.");
544 MODULE_DESCRIPTION("TAS2557 ALSA SOC Smart Amplifier driver");
545 MODULE_LICENSE("GPL v2");
546 #endif