Add compliance for kernel 4.9
[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);
68         return nResult;
69 }
72 static int tas2770_codec_write(struct snd_soc_codec *codec, unsigned int reg,
73         unsigned int value)
74 {
75         struct tas2770_priv *pTAS2770 = snd_soc_codec_get_drvdata(codec);
77         int nResult = 0;
79         mutex_lock(&pTAS2770->dev_lock);
81         nResult = regmap_write(pTAS2770->regmap, reg, value);
82         if(nResult < 0)
83                 dev_err(pTAS2770->dev, "%s, ERROR, reg=0x%x, E=%d\n",
84                         __func__, reg, nResult);
85         else
86                 dev_dbg(pTAS2770->dev, "%s, reg: 0x%x, 0x%x\n", __func__, reg, value);
88         mutex_unlock(&pTAS2770->dev_lock);
90         return nResult;
92 }
95 static int tas2770_codec_suspend(struct snd_soc_codec *codec)
96 {
97         struct tas2770_priv *pTAS2770 = snd_soc_codec_get_drvdata(codec);
98         int ret = 0;
100         mutex_lock(&pTAS2770->codec_lock);
102         dev_dbg(pTAS2770->dev, "%s\n", __func__);
103 //      pTAS2770->runtime_suspend(pTAS2770);
105         mutex_unlock(&pTAS2770->codec_lock);
106         return ret;
109 static int tas2770_codec_resume(struct snd_soc_codec *codec)
111         struct tas2770_priv *pTAS2770 = snd_soc_codec_get_drvdata(codec);
112         int ret = 0;
114         mutex_lock(&pTAS2770->codec_lock);
116         dev_dbg(pTAS2770->dev, "%s\n", __func__);
117 //      pTAS2770->runtime_resume(pTAS2770);
119         mutex_unlock(&pTAS2770->codec_lock);
120         return ret;
123 static const struct snd_kcontrol_new tas2770_asi_controls[] = {
124         SOC_DAPM_SINGLE("Left", TAS2770_TDMConfigurationReg2,
125                 4, 1, 0),
126         SOC_DAPM_SINGLE("Right", TAS2770_TDMConfigurationReg2,
127                 4, 2, 0),
128         SOC_DAPM_SINGLE("LeftRightDiv2", TAS2770_TDMConfigurationReg2,
129                 4, 3, 0),
130 };
133 static int tas2770_dac_event(struct snd_soc_dapm_widget *w,
134                         struct snd_kcontrol *kcontrol, int event) 
136 #if 1
137         struct snd_soc_codec *codec = w->codec;
138 //      struct tas2770_priv *pTAS2770 = snd_soc_codec_get_drvdata(codec);
140         switch (event) {
141         case SND_SOC_DAPM_POST_PMU:
142                 snd_soc_update_bits(codec, TAS2770_PowerControl,
143                         TAS2770_PowerControl_OperationalMode10_Mask,
144                         TAS2770_PowerControl_OperationalMode10_Active);
145                 break;
146         case SND_SOC_DAPM_PRE_PMD:
147                 snd_soc_update_bits(codec, TAS2770_PowerControl,
148                         TAS2770_PowerControl_OperationalMode10_Mask,
149                         TAS2770_PowerControl_OperationalMode10_Shutdown);
150                 break;
151         
152         }
153 #endif
154         return 0;
158 static const struct snd_soc_dapm_widget tas2770_dapm_widgets[] = {
159         SND_SOC_DAPM_AIF_IN("ASI1", "ASI1 Playback", 0, SND_SOC_NOPM, 0, 0),
160         SND_SOC_DAPM_MIXER("ASI1 Sel",
161                 TAS2770_TDMConfigurationReg2, 4, 0,
162                 &tas2770_asi_controls[0],
163                 ARRAY_SIZE(tas2770_asi_controls)),
164         SND_SOC_DAPM_DAC_E("DAC", NULL, SND_SOC_NOPM, 0, 0,
165                 tas2770_dac_event, SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
166         SND_SOC_DAPM_OUTPUT("OUT")
168 };
170 static const struct snd_soc_dapm_route tas2770_audio_map[] = {
171         {"ASI1 Sel", "Left", "ASI1"},
172         {"ASI1 Sel", "Right", "ASI1"},
173         {"ASI1 Sel", "LeftRightDiv2", "ASI1"},
174         {"DAC", NULL, "ASI1 Sel"},
175         {"OUT", NULL, "DAC"},
176 };
179 static int tas2770_mute(struct snd_soc_dai *dai, int mute)
181 #if 1
182         struct snd_soc_codec *codec = dai->codec;
183         struct tas2770_priv *pTAS2770 = snd_soc_codec_get_drvdata(codec);
185         mutex_lock(&pTAS2770->codec_lock);
186         if(mute) {
187                 snd_soc_update_bits(codec, TAS2770_PowerControl,
188                         TAS2770_PowerControl_OperationalMode10_Mask,
189                         TAS2770_PowerControl_OperationalMode10_Mute); 
190         } else {
191                 snd_soc_update_bits(codec, TAS2770_PowerControl,
192                         TAS2770_PowerControl_OperationalMode10_Mask,
193                         TAS2770_PowerControl_OperationalMode10_Active); 
194         }
195         mutex_unlock(&pTAS2770->codec_lock);
196 #endif
197         return 0;
202 static int tas2770_hw_params(struct snd_pcm_substream *substream,
203                 struct snd_pcm_hw_params *params,
204                 struct snd_soc_dai *dai)
206         struct snd_soc_codec *codec = dai->codec;
207         struct tas2770_priv *pTAS2770 = snd_soc_codec_get_drvdata(codec);
208         int blr_clk_ratio;
209         int ret = 0;
211         dev_dbg(pTAS2770->dev, "%s, format: %d\n", __func__, params_format(params));
213         switch(params_format(params)) {
214         case SNDRV_PCM_FORMAT_S16_LE:
215                 snd_soc_update_bits(codec,
216                         TAS2770_TDMConfigurationReg2,
217                         TAS2770_TDMConfigurationReg2_RXWLEN32_Mask |
218                         TAS2770_TDMConfigurationReg2_RXSLEN10_Mask,
219                         TAS2770_TDMConfigurationReg2_RXWLEN32_16Bits |
220                         TAS2770_TDMConfigurationReg2_RXWLEN32_16Bits );
221                         pTAS2770->ch_size = 16;
222                 break;
223         case SNDRV_PCM_FMTBIT_S24_LE:
224                         snd_soc_update_bits(codec,
225                         TAS2770_TDMConfigurationReg2,
226                         TAS2770_TDMConfigurationReg2_RXWLEN32_Mask |
227                         TAS2770_TDMConfigurationReg2_RXSLEN10_Mask,
228                         TAS2770_TDMConfigurationReg2_RXWLEN32_24Bits  |
229                         TAS2770_TDMConfigurationReg2_RXWLEN32_24Bits );
230                         pTAS2770->ch_size = 24;
231                 break;
232         case SNDRV_PCM_FMTBIT_S32_LE:
233                         snd_soc_update_bits(codec,
234                         TAS2770_TDMConfigurationReg2,
235                         TAS2770_TDMConfigurationReg2_RXWLEN32_Mask |
236                         TAS2770_TDMConfigurationReg2_RXSLEN10_Mask,
237                         TAS2770_TDMConfigurationReg2_RXWLEN32_32Bits |
238                         TAS2770_TDMConfigurationReg2_RXWLEN32_32Bits );
239                         pTAS2770->ch_size = 32;
240                 break;
242         }
244         blr_clk_ratio = params_channels(params) * pTAS2770->ch_size;
245         dev_dbg(pTAS2770->dev, "blr_clk_ratio: %d\n", blr_clk_ratio);
247         switch(blr_clk_ratio) {
248         case 16: 
249                         snd_soc_update_bits(codec,
250                                 TAS2770_ClockConfiguration,
251                                 TAS2770_ClockConfiguration_SBCLKtoFS52_Mask,
252                                 TAS2770_ClockConfiguration_SBCLKtoFS52_16);
253                         break;
254         case 24:
255                         snd_soc_update_bits(codec,
256                                 TAS2770_ClockConfiguration,
257                                 TAS2770_ClockConfiguration_SBCLKtoFS52_Mask,
258                                 TAS2770_ClockConfiguration_SBCLKtoFS52_24);
259                         break;
260         case 32:
261                         snd_soc_update_bits(codec,
262                                 TAS2770_ClockConfiguration,
263                                 TAS2770_ClockConfiguration_SBCLKtoFS52_Mask,
264                                 TAS2770_ClockConfiguration_SBCLKtoFS52_32);
265                         break;
266         case 48: 
267                         snd_soc_update_bits(codec,
268                                 TAS2770_ClockConfiguration,
269                                 TAS2770_ClockConfiguration_SBCLKtoFS52_Mask,
270                                 TAS2770_ClockConfiguration_SBCLKtoFS52_48);
271                         break;                  
272         case 64:                        
273                         snd_soc_update_bits(codec,
274                                 TAS2770_ClockConfiguration,
275                                 TAS2770_ClockConfiguration_SBCLKtoFS52_Mask,
276                                 TAS2770_ClockConfiguration_SBCLKtoFS52_64);
277                         break;
278         case 96:                        
279                         snd_soc_update_bits(codec,
280                                 TAS2770_ClockConfiguration,
281                                 TAS2770_ClockConfiguration_SBCLKtoFS52_Mask,
282                                 TAS2770_ClockConfiguration_SBCLKtoFS52_96);
283                         break;
284         case 128:                       
285                         snd_soc_update_bits(codec,
286                                 TAS2770_ClockConfiguration,
287                                 TAS2770_ClockConfiguration_SBCLKtoFS52_Mask,
288                                 TAS2770_ClockConfiguration_SBCLKtoFS52_128);
289                         break;                  
290         case 192:                       
291                         snd_soc_update_bits(codec,
292                                 TAS2770_ClockConfiguration,
293                                 TAS2770_ClockConfiguration_SBCLKtoFS52_Mask,
294                                 TAS2770_ClockConfiguration_SBCLKtoFS52_192);
295                         break;
296         case 256:                       
297                         snd_soc_update_bits(codec,
298                                 TAS2770_ClockConfiguration,
299                                 TAS2770_ClockConfiguration_SBCLKtoFS52_Mask,
300                                 TAS2770_ClockConfiguration_SBCLKtoFS52_256);
301                         break;
302         case 384:                       
303                         snd_soc_update_bits(codec,
304                                 TAS2770_ClockConfiguration,
305                                 TAS2770_ClockConfiguration_SBCLKtoFS52_Mask,
306                                 TAS2770_ClockConfiguration_SBCLKtoFS52_384);
307                         break;                  
308         case 512:                       
309                         snd_soc_update_bits(codec,
310                                 TAS2770_ClockConfiguration,
311                                 TAS2770_ClockConfiguration_SBCLKtoFS52_Mask,
312                                 TAS2770_ClockConfiguration_SBCLKtoFS52_512);
313                         break;
314         default:
315                 dev_err(pTAS2770->dev, "Invalid BCLK to FSYNC ratio\n");
316                 ret = -EINVAL;
317         }
319         dev_dbg(pTAS2770->dev, "%s, sample rate: %d\n", __func__, params_rate(params));
320         switch(params_rate(params))
321         {
322                 case 48000:
323                         snd_soc_update_bits(codec,
324                                 TAS2770_TDMConfigurationReg0,
325                                 TAS2770_TDMConfigurationReg0_SAMPRATERAMP_Mask,
326                                 TAS2770_TDMConfigurationReg0_SAMPRATERAMP_48KHz);
327                         snd_soc_update_bits(codec,
328                                 TAS2770_TDMConfigurationReg0,
329                                 TAS2770_TDMConfigurationReg0_SAMPRATE31_Mask,
330                                 TAS2770_TDMConfigurationReg0_SAMPRATE31_44_1_48kHz);
331                         break;
332                 case 44100:
333                         snd_soc_update_bits(codec,
334                                 TAS2770_TDMConfigurationReg0,
335                                 TAS2770_TDMConfigurationReg0_SAMPRATERAMP_Mask,
336                                 TAS2770_TDMConfigurationReg0_SAMPRATERAMP_44_1KHz);
337                         snd_soc_update_bits(codec,
338                                 TAS2770_TDMConfigurationReg0,
339                                 TAS2770_TDMConfigurationReg0_SAMPRATE31_Mask,
340                                 TAS2770_TDMConfigurationReg0_SAMPRATE31_44_1_48kHz);
341                         break;
342                 case 96000:
343                         snd_soc_update_bits(codec,
344                                 TAS2770_TDMConfigurationReg0,
345                                 TAS2770_TDMConfigurationReg0_SAMPRATERAMP_Mask,
346                                 TAS2770_TDMConfigurationReg0_SAMPRATERAMP_48KHz);
347                         snd_soc_update_bits(codec,
348                                 TAS2770_TDMConfigurationReg0,
349                                 TAS2770_TDMConfigurationReg0_SAMPRATE31_Mask,
350                                 TAS2770_TDMConfigurationReg0_SAMPRATE31_88_2_96kHz);
351                         break;
352                 case 88200:
353                         snd_soc_update_bits(codec,
354                                 TAS2770_TDMConfigurationReg0,
355                                 TAS2770_TDMConfigurationReg0_SAMPRATERAMP_Mask,
356                                 TAS2770_TDMConfigurationReg0_SAMPRATERAMP_44_1KHz);
357                         snd_soc_update_bits(codec,
358                                 TAS2770_TDMConfigurationReg0,
359                                 TAS2770_TDMConfigurationReg0_SAMPRATE31_Mask,
360                                 TAS2770_TDMConfigurationReg0_SAMPRATE31_88_2_96kHz);
361                         break;
362                 case 19200:
363                         snd_soc_update_bits(codec,
364                                 TAS2770_TDMConfigurationReg0,
365                                 TAS2770_TDMConfigurationReg0_SAMPRATERAMP_Mask,
366                                 TAS2770_TDMConfigurationReg0_SAMPRATERAMP_48KHz);
367                         snd_soc_update_bits(codec,
368                                 TAS2770_TDMConfigurationReg0,
369                                 TAS2770_TDMConfigurationReg0_SAMPRATE31_Mask,
370                                 TAS2770_TDMConfigurationReg0_SAMPRATE31_176_4_192kHz);
371                         break;
372                 case 17640:
373                         snd_soc_update_bits(codec,
374                                 TAS2770_TDMConfigurationReg0,
375                                 TAS2770_TDMConfigurationReg0_SAMPRATERAMP_Mask,
376                                 TAS2770_TDMConfigurationReg0_SAMPRATERAMP_44_1KHz);
377                         snd_soc_update_bits(codec,
378                                 TAS2770_TDMConfigurationReg0,
379                                 TAS2770_TDMConfigurationReg0_SAMPRATE31_Mask,
380                                 TAS2770_TDMConfigurationReg0_SAMPRATE31_176_4_192kHz);
381                         break;
382                 default:
383                         dev_dbg(pTAS2770->dev, "%s, unsupported sample rate\n", __func__);
384                         
385         }
386         return ret;
389 static int tas2770_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
391         u8 tdm_rx_start_slot = 0, asi_cfg_1 = 0;
392         struct snd_soc_codec *codec = dai->codec;
393         struct tas2770_priv *pTAS2770 = snd_soc_codec_get_drvdata(codec);
394         int ret = 0;
396         dev_dbg(pTAS2770->dev, "%s, format=0x%x\n", __func__, fmt);
398 #if 1
399         switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
400         case SND_SOC_DAIFMT_CBS_CFS: 
401                 asi_cfg_1 = 0x00;
402                 break;
403         default:
404                 dev_err(pTAS2770->dev, "ASI format master is not found\n");
405                 ret = -EINVAL;
406         }
408         switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
409         case SND_SOC_DAIFMT_NB_NF:
410                 dev_dbg(pTAS2770->dev, "INV format: NBNF\n");
411                 asi_cfg_1 |= TAS2770_TDMConfigurationReg1_RXEDGE_Rising;
412                 break;
413         case SND_SOC_DAIFMT_IB_NF:
414                 dev_dbg(pTAS2770->dev, "INV format: IBNF\n");
415                 asi_cfg_1 |= TAS2770_TDMConfigurationReg1_RXEDGE_Falling;
416                 break;
417         default:
418                 dev_err(pTAS2770->dev, "ASI format Inverse is not found\n");
419                 ret = -EINVAL;
420         }
422         snd_soc_update_bits(codec, TAS2770_TDMConfigurationReg1, 
423                 TAS2770_TDMConfigurationReg1_RXEDGE_Mask,
424                 asi_cfg_1);
426         switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
427         case (SND_SOC_DAIFMT_I2S):
428                 tdm_rx_start_slot = 1;
429                 break;
430         case (SND_SOC_DAIFMT_DSP_A):
431         case (SND_SOC_DAIFMT_DSP_B):
432                 tdm_rx_start_slot = 1;
433                 break;
434         case (SND_SOC_DAIFMT_LEFT_J):
435                 tdm_rx_start_slot = 0;
436                 break;
437         default:
438                 dev_err(pTAS2770->dev, "DAI Format is not found, fmt=0x%x\n", fmt);
439                 ret = -EINVAL;
440                 break;
441         }
443         snd_soc_update_bits(codec, TAS2770_TDMConfigurationReg1, 
444                 TAS2770_TDMConfigurationReg1_RXOFFSET51_Mask,
445                 (tdm_rx_start_slot << TAS2770_TDMConfigurationReg1_RXOFFSET51_Shift));
446 #endif
447         return ret;
450 static struct snd_soc_dai_ops tas2770_dai_ops = {
451         .digital_mute = tas2770_mute,
452         .hw_params  = tas2770_hw_params,
453         .set_fmt    = tas2770_set_dai_fmt,
454 };
456 #define TAS2770_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
457                 SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
459 #define TAS2770_RATES (SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 \
460                                                 SNDRV_PCM_RATE_88200 |\
461                                                 SNDRV_PCM_RATE_96000 |\
462                                                 SNDRV_PCM_RATE_176400 |\
463                                                 SNDRV_PCM_RATE_192000\
464                                                 )
466 static struct snd_soc_dai_driver tas2770_dai_driver[] = {
467         {
468                 .name = "tas2770 ASI1",
469                 .id = 0,
470                 .playback = {
471                         .stream_name    = "ASI1 Playback",
472                         .channels_min   = 2,
473                         .channels_max   = 2,
474                         .rates      = SNDRV_PCM_RATE_8000_192000,
475                         .formats    = TAS2770_FORMATS,
476                 },
477                 .capture = {
478                         .stream_name    = "ASI1 Capture",
479                         .channels_min   = 0,
480                         .channels_max   = 2,
481                         .rates          = SNDRV_PCM_RATE_8000_192000,
482                         .formats    = TAS2770_FORMATS,  
483                 },
484                 .ops = &tas2770_dai_ops,
485                 .symmetric_rates = 1,
486         },
487 };
489 static int tas2770_codec_probe(struct snd_soc_codec *codec)
491         struct tas2770_priv *pTAS2770 = snd_soc_codec_get_drvdata(codec);
493         dev_err(pTAS2770->dev, "%s\n", __func__);
495         return 0;
498 static int tas2770_codec_remove(struct snd_soc_codec *codec)
500         return 0;
503 #if 0
505 /*
506  * DAC digital volumes. From 0 to 31 dB in 1 dB steps
507  */
508 static DECLARE_TLV_DB_SCALE(dac_tlv, 0, 100, 0);
510 static const struct snd_kcontrol_new tas2770_snd_controls[] = {
511         SOC_SINGLE_TLV("DAC Playback Volume", TAS2770_PlaybackConfigurationReg0, 0, 0x1f, 0,
512                         dac_tlv),
513 //      SOC_SINGLE_EXT("TAS2770 PowerCtrl", SND_SOC_NOPM, 0, 0x0001, 0,
514 //                      tas2770_power_ctrl_get, tas2770_power_ctrl_put),
515 };
516 #endif
518 static struct snd_soc_codec_driver soc_codec_driver_tas2770 = {
519         .probe                  = tas2770_codec_probe,
520         .remove                 = tas2770_codec_remove,
521         .read                   = tas2770_codec_read,
522         .write                  = tas2770_codec_write,
523         .suspend                = tas2770_codec_suspend,
524         .resume                 = tas2770_codec_resume,
525         .component_driver = {
526 //              .controls               = tas2770_snd_controls,
527 //              .num_controls           = ARRAY_SIZE(tas2770_snd_controls),
528                 .dapm_widgets           = tas2770_dapm_widgets,
529                 .num_dapm_widgets       = ARRAY_SIZE(tas2770_dapm_widgets),
530                 .dapm_routes            = tas2770_audio_map,
531                 .num_dapm_routes        = ARRAY_SIZE(tas2770_audio_map),
532         },
533 };
535 int tas2770_register_codec(struct tas2770_priv *pTAS2770)
537         int nResult = 0;
539         dev_info(pTAS2770->dev, "%s, enter\n", __func__);
540         nResult = snd_soc_register_codec(pTAS2770->dev,
541                 &soc_codec_driver_tas2770,
542                 tas2770_dai_driver, ARRAY_SIZE(tas2770_dai_driver));
544         return nResult;
547 int tas2770_deregister_codec(struct tas2770_priv *pTAS2770)
549         snd_soc_unregister_codec(pTAS2770->dev);
551         return 0;
554 MODULE_AUTHOR("Texas Instruments Inc.");
555 MODULE_DESCRIPTION("TAS2770 ALSA SOC Smart Amplifier driver");
556 MODULE_LICENSE("GPL v2");
557 #endif /* CONFIG_TAS2770_CODEC */