9d75894a67f915645170ed87ef17b6edd6050c0f
[tas2770sw-android/tas2770sw-android.git] / tas2770-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 **     tas2770-codec.c
15 **
16 ** Description:
17 **     ALSA SoC driver for Texas Instruments TAS2770 High Performance 4W Smart Amplifier
18 **
19 ** =============================================================================
20 */
22 #ifdef CONFIG_TAS2770_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 <sound/core.h>
39 #include <sound/pcm.h>
40 #include <sound/pcm_params.h>
41 #include <sound/soc.h>
42 #include <sound/initval.h>
43 #include <sound/tlv.h>
45 #include "tas2770.h"
48 #define TAS2770_MDELAY 0xFFFFFFFE
49 //#define KCONTROL_CODEC
51 static unsigned int tas2770_codec_read(struct snd_soc_codec *codec,  unsigned int reg)
52 {
53         struct tas2770_priv *pTAS2770 = snd_soc_codec_get_drvdata(codec);
54         int nResult = 0;
55         unsigned int value = 0;
57         mutex_lock(&pTAS2770->dev_lock);
59         nResult = regmap_read(pTAS2770->regmap, reg, &value);
61         if (nResult < 0)
62                 dev_err(pTAS2770->dev, "%s, ERROR, reg=0x%x, E=%d\n",
63                         __func__, reg, nResult);
64         else
65                 dev_dbg(pTAS2770->dev, "%s, reg: 0x%x, value: 0x%x\n", __func__, reg, value);
67         mutex_unlock(&pTAS2770->dev_lock);
69         if(nResult >= 0)
70                 return value;
71         else
72                 return nResult;
73 }
76 static int tas2770_codec_write(struct snd_soc_codec *codec, unsigned int reg,
77         unsigned int value)
78 {
79         struct tas2770_priv *pTAS2770 = snd_soc_codec_get_drvdata(codec);
81         int nResult = 0;
83         mutex_lock(&pTAS2770->dev_lock);
85         nResult = regmap_write(pTAS2770->regmap, reg, value);
86         if(nResult < 0)
87                 dev_err(pTAS2770->dev, "%s, ERROR, reg=0x%x, E=%d\n",
88                         __func__, reg, nResult);
89         else
90                 dev_dbg(pTAS2770->dev, "%s, reg: 0x%x, 0x%x\n", __func__, reg, value);
92         mutex_unlock(&pTAS2770->dev_lock);
94         return nResult;
96 }
99 static int tas2770_codec_suspend(struct snd_soc_codec *codec)
101         struct tas2770_priv *pTAS2770 = snd_soc_codec_get_drvdata(codec);
102         int ret = 0;
104         mutex_lock(&pTAS2770->codec_lock);
106         dev_dbg(pTAS2770->dev, "%s\n", __func__);
107 //      pTAS2770->runtime_suspend(pTAS2770);
109         mutex_unlock(&pTAS2770->codec_lock);
110         return ret;
113 static int tas2770_codec_resume(struct snd_soc_codec *codec)
115         struct tas2770_priv *pTAS2770 = snd_soc_codec_get_drvdata(codec);
116         int ret = 0;
118         mutex_lock(&pTAS2770->codec_lock);
120         dev_dbg(pTAS2770->dev, "%s\n", __func__);
121 //      pTAS2770->runtime_resume(pTAS2770);
123         mutex_unlock(&pTAS2770->codec_lock);
124         return ret;
127 static const struct snd_kcontrol_new tas2770_asi_controls[] = {
128         SOC_DAPM_SINGLE("Left", TAS2770_TDMConfigurationReg2,
129                 4, 1, 0),
130         SOC_DAPM_SINGLE("Right", TAS2770_TDMConfigurationReg2,
131                 4, 2, 0),
132         SOC_DAPM_SINGLE("LeftRightDiv2", TAS2770_TDMConfigurationReg2,
133                 4, 3, 0),
134 };
137 static int tas2770_dac_event(struct snd_soc_dapm_widget *w,
138                         struct snd_kcontrol *kcontrol, int event) 
140 #if 1
141         struct snd_soc_codec *codec = w->codec;
142 //      struct tas2770_priv *pTAS2770 = snd_soc_codec_get_drvdata(codec);
144         switch (event) {
145         case SND_SOC_DAPM_POST_PMU:
146                 snd_soc_update_bits(codec, TAS2770_PowerControl,
147                         TAS2770_PowerControl_OperationalMode10_Mask,
148                         TAS2770_PowerControl_OperationalMode10_Active);
149                 break;
150         case SND_SOC_DAPM_PRE_PMD:
151                 snd_soc_update_bits(codec, TAS2770_PowerControl,
152                         TAS2770_PowerControl_OperationalMode10_Mask,
153                         TAS2770_PowerControl_OperationalMode10_Shutdown);
154                 break;
155         
156         }
157 #endif
158         return 0;
162 static const struct snd_soc_dapm_widget tas2770_dapm_widgets[] = {
163         SND_SOC_DAPM_AIF_IN("ASI1", "ASI1 Playback", 0, SND_SOC_NOPM, 0, 0),
164         SND_SOC_DAPM_MIXER("ASI1 Sel",
165                 TAS2770_TDMConfigurationReg2, 4, 0,
166                 &tas2770_asi_controls[0],
167                 ARRAY_SIZE(tas2770_asi_controls)),
168         SND_SOC_DAPM_DAC_E("DAC", NULL, SND_SOC_NOPM, 0, 0,
169                 tas2770_dac_event, SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
170         SND_SOC_DAPM_OUTPUT("OUT")
172 };
174 static const struct snd_soc_dapm_route tas2770_audio_map[] = {
175         {"ASI1 Sel", "Left", "ASI1"},
176         {"ASI1 Sel", "Right", "ASI1"},
177         {"ASI1 Sel", "LeftRightDiv2", "ASI1"},
178         {"DAC", NULL, "ASI1 Sel"},
179         {"OUT", NULL, "DAC"},
180 };
183 static int tas2770_mute(struct snd_soc_dai *dai, int mute)
185 #if 1
186         struct snd_soc_codec *codec = dai->codec;
187         struct tas2770_priv *pTAS2770 = snd_soc_codec_get_drvdata(codec);
189         mutex_lock(&pTAS2770->codec_lock);
190         if(mute) {
191                 snd_soc_update_bits(codec, TAS2770_PowerControl,
192                         TAS2770_PowerControl_OperationalMode10_Mask,
193                         TAS2770_PowerControl_OperationalMode10_Mute); 
194         } else {
195                 snd_soc_update_bits(codec, TAS2770_PowerControl,
196                         TAS2770_PowerControl_OperationalMode10_Mask,
197                         TAS2770_PowerControl_OperationalMode10_Active); 
198         }
199         mutex_unlock(&pTAS2770->codec_lock);
200 #endif
201         return 0;
206 static int tas2770_hw_params(struct snd_pcm_substream *substream,
207                 struct snd_pcm_hw_params *params,
208                 struct snd_soc_dai *dai)
210         struct snd_soc_codec *codec = dai->codec;
211         struct tas2770_priv *pTAS2770 = snd_soc_codec_get_drvdata(codec);
212         int blr_clk_ratio;
213         int ret = 0;
215         dev_dbg(pTAS2770->dev, "%s, format: %d\n", __func__, params_format(params));
217         switch(params_format(params)) {
218         case SNDRV_PCM_FORMAT_S16_LE:
219                 snd_soc_update_bits(codec,
220                         TAS2770_TDMConfigurationReg2,
221                         TAS2770_TDMConfigurationReg2_RXWLEN32_Mask |
222                         TAS2770_TDMConfigurationReg2_RXSLEN10_Mask,
223                         TAS2770_TDMConfigurationReg2_RXWLEN32_16Bits |
224                         TAS2770_TDMConfigurationReg2_RXWLEN32_16Bits );
225                         pTAS2770->ch_size = 16;
226                 break;
227         case SNDRV_PCM_FMTBIT_S24_LE:
228                         snd_soc_update_bits(codec,
229                         TAS2770_TDMConfigurationReg2,
230                         TAS2770_TDMConfigurationReg2_RXWLEN32_Mask |
231                         TAS2770_TDMConfigurationReg2_RXSLEN10_Mask,
232                         TAS2770_TDMConfigurationReg2_RXWLEN32_24Bits  |
233                         TAS2770_TDMConfigurationReg2_RXWLEN32_24Bits );
234                         pTAS2770->ch_size = 24;
235                 break;
236         case SNDRV_PCM_FMTBIT_S32_LE:
237                         snd_soc_update_bits(codec,
238                         TAS2770_TDMConfigurationReg2,
239                         TAS2770_TDMConfigurationReg2_RXWLEN32_Mask |
240                         TAS2770_TDMConfigurationReg2_RXSLEN10_Mask,
241                         TAS2770_TDMConfigurationReg2_RXWLEN32_32Bits |
242                         TAS2770_TDMConfigurationReg2_RXWLEN32_32Bits );
243                         pTAS2770->ch_size = 32;
244                 break;
246         }
248         blr_clk_ratio = params_channels(params) * pTAS2770->ch_size;
249         dev_dbg(pTAS2770->dev, "blr_clk_ratio: %d\n", blr_clk_ratio);
251         switch(blr_clk_ratio) {
252         case 16: 
253                         snd_soc_update_bits(codec,
254                                 TAS2770_ClockConfiguration,
255                                 TAS2770_ClockConfiguration_SBCLKtoFS52_Mask,
256                                 TAS2770_ClockConfiguration_SBCLKtoFS52_16);
257                         break;
258         case 24:
259                         snd_soc_update_bits(codec,
260                                 TAS2770_ClockConfiguration,
261                                 TAS2770_ClockConfiguration_SBCLKtoFS52_Mask,
262                                 TAS2770_ClockConfiguration_SBCLKtoFS52_24);
263                         break;
264         case 32:
265                         snd_soc_update_bits(codec,
266                                 TAS2770_ClockConfiguration,
267                                 TAS2770_ClockConfiguration_SBCLKtoFS52_Mask,
268                                 TAS2770_ClockConfiguration_SBCLKtoFS52_32);
269                         break;
270         case 48: 
271                         snd_soc_update_bits(codec,
272                                 TAS2770_ClockConfiguration,
273                                 TAS2770_ClockConfiguration_SBCLKtoFS52_Mask,
274                                 TAS2770_ClockConfiguration_SBCLKtoFS52_48);
275                         break;                  
276         case 64:                        
277                         snd_soc_update_bits(codec,
278                                 TAS2770_ClockConfiguration,
279                                 TAS2770_ClockConfiguration_SBCLKtoFS52_Mask,
280                                 TAS2770_ClockConfiguration_SBCLKtoFS52_64);
281                         break;
282         case 96:                        
283                         snd_soc_update_bits(codec,
284                                 TAS2770_ClockConfiguration,
285                                 TAS2770_ClockConfiguration_SBCLKtoFS52_Mask,
286                                 TAS2770_ClockConfiguration_SBCLKtoFS52_96);
287                         break;
288         case 128:                       
289                         snd_soc_update_bits(codec,
290                                 TAS2770_ClockConfiguration,
291                                 TAS2770_ClockConfiguration_SBCLKtoFS52_Mask,
292                                 TAS2770_ClockConfiguration_SBCLKtoFS52_128);
293                         break;                  
294         case 192:                       
295                         snd_soc_update_bits(codec,
296                                 TAS2770_ClockConfiguration,
297                                 TAS2770_ClockConfiguration_SBCLKtoFS52_Mask,
298                                 TAS2770_ClockConfiguration_SBCLKtoFS52_192);
299                         break;
300         case 256:                       
301                         snd_soc_update_bits(codec,
302                                 TAS2770_ClockConfiguration,
303                                 TAS2770_ClockConfiguration_SBCLKtoFS52_Mask,
304                                 TAS2770_ClockConfiguration_SBCLKtoFS52_256);
305                         break;
306         case 384:                       
307                         snd_soc_update_bits(codec,
308                                 TAS2770_ClockConfiguration,
309                                 TAS2770_ClockConfiguration_SBCLKtoFS52_Mask,
310                                 TAS2770_ClockConfiguration_SBCLKtoFS52_384);
311                         break;                  
312         case 512:                       
313                         snd_soc_update_bits(codec,
314                                 TAS2770_ClockConfiguration,
315                                 TAS2770_ClockConfiguration_SBCLKtoFS52_Mask,
316                                 TAS2770_ClockConfiguration_SBCLKtoFS52_512);
317                         break;
318         default:
319                 dev_err(pTAS2770->dev, "Invalid BCLK to FSYNC ratio\n");
320                 ret = -EINVAL;
321         }
323         dev_dbg(pTAS2770->dev, "%s, sample rate: %d\n", __func__, params_rate(params));
324         switch(params_rate(params))
325         {
326                 case 48000:
327                         snd_soc_update_bits(codec,
328                                 TAS2770_TDMConfigurationReg0,
329                                 TAS2770_TDMConfigurationReg0_SAMPRATERAMP_Mask,
330                                 TAS2770_TDMConfigurationReg0_SAMPRATERAMP_48KHz);
331                         snd_soc_update_bits(codec,
332                                 TAS2770_TDMConfigurationReg0,
333                                 TAS2770_TDMConfigurationReg0_SAMPRATE31_Mask,
334                                 TAS2770_TDMConfigurationReg0_SAMPRATE31_44_1_48kHz);
335                         break;
336                 case 44100:
337                         snd_soc_update_bits(codec,
338                                 TAS2770_TDMConfigurationReg0,
339                                 TAS2770_TDMConfigurationReg0_SAMPRATERAMP_Mask,
340                                 TAS2770_TDMConfigurationReg0_SAMPRATERAMP_44_1KHz);
341                         snd_soc_update_bits(codec,
342                                 TAS2770_TDMConfigurationReg0,
343                                 TAS2770_TDMConfigurationReg0_SAMPRATE31_Mask,
344                                 TAS2770_TDMConfigurationReg0_SAMPRATE31_44_1_48kHz);
345                         break;
346                 case 96000:
347                         snd_soc_update_bits(codec,
348                                 TAS2770_TDMConfigurationReg0,
349                                 TAS2770_TDMConfigurationReg0_SAMPRATERAMP_Mask,
350                                 TAS2770_TDMConfigurationReg0_SAMPRATERAMP_48KHz);
351                         snd_soc_update_bits(codec,
352                                 TAS2770_TDMConfigurationReg0,
353                                 TAS2770_TDMConfigurationReg0_SAMPRATE31_Mask,
354                                 TAS2770_TDMConfigurationReg0_SAMPRATE31_88_2_96kHz);
355                         break;
356                 case 88200:
357                         snd_soc_update_bits(codec,
358                                 TAS2770_TDMConfigurationReg0,
359                                 TAS2770_TDMConfigurationReg0_SAMPRATERAMP_Mask,
360                                 TAS2770_TDMConfigurationReg0_SAMPRATERAMP_44_1KHz);
361                         snd_soc_update_bits(codec,
362                                 TAS2770_TDMConfigurationReg0,
363                                 TAS2770_TDMConfigurationReg0_SAMPRATE31_Mask,
364                                 TAS2770_TDMConfigurationReg0_SAMPRATE31_88_2_96kHz);
365                         break;
366                 case 19200:
367                         snd_soc_update_bits(codec,
368                                 TAS2770_TDMConfigurationReg0,
369                                 TAS2770_TDMConfigurationReg0_SAMPRATERAMP_Mask,
370                                 TAS2770_TDMConfigurationReg0_SAMPRATERAMP_48KHz);
371                         snd_soc_update_bits(codec,
372                                 TAS2770_TDMConfigurationReg0,
373                                 TAS2770_TDMConfigurationReg0_SAMPRATE31_Mask,
374                                 TAS2770_TDMConfigurationReg0_SAMPRATE31_176_4_192kHz);
375                         break;
376                 case 17640:
377                         snd_soc_update_bits(codec,
378                                 TAS2770_TDMConfigurationReg0,
379                                 TAS2770_TDMConfigurationReg0_SAMPRATERAMP_Mask,
380                                 TAS2770_TDMConfigurationReg0_SAMPRATERAMP_44_1KHz);
381                         snd_soc_update_bits(codec,
382                                 TAS2770_TDMConfigurationReg0,
383                                 TAS2770_TDMConfigurationReg0_SAMPRATE31_Mask,
384                                 TAS2770_TDMConfigurationReg0_SAMPRATE31_176_4_192kHz);
385                         break;
386                 default:
387                         dev_dbg(pTAS2770->dev, "%s, unsupported sample rate\n", __func__);
388                         
389         }
390         return ret;
393 static int tas2770_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
395         u8 tdm_rx_start_slot = 0, asi_cfg_1 = 0;
396         struct snd_soc_codec *codec = dai->codec;
397         struct tas2770_priv *pTAS2770 = snd_soc_codec_get_drvdata(codec);
398         int ret = 0;
400         dev_dbg(pTAS2770->dev, "%s, format=0x%x\n", __func__, fmt);
402 #if 1
403         switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
404         case SND_SOC_DAIFMT_CBS_CFS: 
405                 asi_cfg_1 = 0x00;
406                 break;
407         default:
408                 dev_err(pTAS2770->dev, "ASI format master is not found\n");
409                 ret = -EINVAL;
410         }
412         switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
413         case SND_SOC_DAIFMT_NB_NF:
414                 dev_dbg(pTAS2770->dev, "INV format: NBNF\n");
415                 asi_cfg_1 |= TAS2770_TDMConfigurationReg1_RXEDGE_Rising;
416                 break;
417         case SND_SOC_DAIFMT_IB_NF:
418                 dev_dbg(pTAS2770->dev, "INV format: IBNF\n");
419                 asi_cfg_1 |= TAS2770_TDMConfigurationReg1_RXEDGE_Falling;
420                 break;
421         default:
422                 dev_err(pTAS2770->dev, "ASI format Inverse is not found\n");
423                 ret = -EINVAL;
424         }
426         snd_soc_update_bits(codec, TAS2770_TDMConfigurationReg1, 
427                 TAS2770_TDMConfigurationReg1_RXEDGE_Mask,
428                 asi_cfg_1);
430         switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
431         case (SND_SOC_DAIFMT_I2S):
432                 tdm_rx_start_slot = 1;
433                 break;
434         case (SND_SOC_DAIFMT_DSP_A):
435         case (SND_SOC_DAIFMT_DSP_B):
436                 tdm_rx_start_slot = 1;
437                 break;
438         case (SND_SOC_DAIFMT_LEFT_J):
439                 tdm_rx_start_slot = 0;
440                 break;
441         default:
442                 dev_err(pTAS2770->dev, "DAI Format is not found, fmt=0x%x\n", fmt);
443                 ret = -EINVAL;
444                 break;
445         }
447         snd_soc_update_bits(codec, TAS2770_TDMConfigurationReg1, 
448                 TAS2770_TDMConfigurationReg1_RXOFFSET51_Mask,
449                 (tdm_rx_start_slot << TAS2770_TDMConfigurationReg1_RXOFFSET51_Shift));
450 #endif
451         return ret;
454 static struct snd_soc_dai_ops tas2770_dai_ops = {
455         .digital_mute = tas2770_mute,
456         .hw_params  = tas2770_hw_params,
457         .set_fmt    = tas2770_set_dai_fmt,
458 };
460 #define TAS2770_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
461                 SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
463 #define TAS2770_RATES (SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 \
464                                                 SNDRV_PCM_RATE_88200 |\
465                                                 SNDRV_PCM_RATE_96000 |\
466                                                 SNDRV_PCM_RATE_176400 |\
467                                                 SNDRV_PCM_RATE_192000\
468                                                 )
470 static struct snd_soc_dai_driver tas2770_dai_driver[] = {
471         {
472                 .name = "tas2770 ASI1",
473                 .id = 0,
474                 .playback = {
475                         .stream_name    = "ASI1 Playback",
476                         .channels_min   = 2,
477                         .channels_max   = 2,
478                         .rates      = SNDRV_PCM_RATE_8000_192000,
479                         .formats    = TAS2770_FORMATS,
480                 },
481                 .capture = {
482                         .stream_name    = "ASI1 Capture",
483                         .channels_min   = 0,
484                         .channels_max   = 2,
485                         .rates          = SNDRV_PCM_RATE_8000_192000,
486                         .formats    = TAS2770_FORMATS,  
487                 },
488                 .ops = &tas2770_dai_ops,
489                 .symmetric_rates = 1,
490         },
491 };
493 static int tas2770_codec_probe(struct snd_soc_codec *codec)
495         struct tas2770_priv *pTAS2770 = snd_soc_codec_get_drvdata(codec);
497         dev_err(pTAS2770->dev, "%s\n", __func__);
499         return 0;
502 static int tas2770_codec_remove(struct snd_soc_codec *codec)
504         return 0;
507 #if 0
509 /*
510  * DAC digital volumes. From 0 to 31 dB in 1 dB steps
511  */
512 static DECLARE_TLV_DB_SCALE(dac_tlv, 0, 100, 0);
514 static const struct snd_kcontrol_new tas2770_snd_controls[] = {
515         SOC_SINGLE_TLV("DAC Playback Volume", TAS2770_PlaybackConfigurationReg0, 0, 0x1f, 0,
516                         dac_tlv),
517 //      SOC_SINGLE_EXT("TAS2770 PowerCtrl", SND_SOC_NOPM, 0, 0x0001, 0,
518 //                      tas2770_power_ctrl_get, tas2770_power_ctrl_put),
519 };
520 #endif
522 static struct snd_soc_codec_driver soc_codec_driver_tas2770 = {
523         .probe                  = tas2770_codec_probe,
524         .remove                 = tas2770_codec_remove,
525         .read                   = tas2770_codec_read,
526         .write                  = tas2770_codec_write,
527         .suspend                = tas2770_codec_suspend,
528         .resume                 = tas2770_codec_resume,
529         .component_driver = {
530 //              .controls               = tas2770_snd_controls,
531 //              .num_controls           = ARRAY_SIZE(tas2770_snd_controls),
532                 .dapm_widgets           = tas2770_dapm_widgets,
533                 .num_dapm_widgets       = ARRAY_SIZE(tas2770_dapm_widgets),
534                 .dapm_routes            = tas2770_audio_map,
535                 .num_dapm_routes        = ARRAY_SIZE(tas2770_audio_map),
536         },
537 };
539 int tas2770_register_codec(struct tas2770_priv *pTAS2770)
541         int nResult = 0;
543         dev_info(pTAS2770->dev, "%s, enter\n", __func__);
544         nResult = snd_soc_register_codec(pTAS2770->dev,
545                 &soc_codec_driver_tas2770,
546                 tas2770_dai_driver, ARRAY_SIZE(tas2770_dai_driver));
548         return nResult;
551 int tas2770_deregister_codec(struct tas2770_priv *pTAS2770)
553         snd_soc_unregister_codec(pTAS2770->dev);
555         return 0;
558 MODULE_AUTHOR("Texas Instruments Inc.");
559 MODULE_DESCRIPTION("TAS2770 ALSA SOC Smart Amplifier driver");
560 MODULE_LICENSE("GPL v2");
561 #endif /* CONFIG_TAS2770_CODEC */