asoc: tegra-alt: Set I2S2 bclk ratio and slot ctrl
[linux-3.10.git] / sound / soc / tegra-alt / tegra_t210ref_mobile_es755_alt.c
1 /*
2  * tegra_t210ref_mobile.c - Tegra T210 Machine driver for mobile
3  *
4  * Copyright (c) 2013-2014 NVIDIA CORPORATION.  All rights reserved.
5  *
6  * This program is free software; you can redistribute it and/or modify it
7  * under the terms and conditions of the GNU General Public License,
8  * version 2, as published by the Free Software Foundation.
9  *
10  * This program is distributed in the hope it will be useful, but WITHOUT
11  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
13  * more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
17  */
18
19 #include <linux/module.h>
20 #include <linux/platform_device.h>
21 #include <linux/slab.h>
22 #include <linux/gpio.h>
23 #include <linux/of_gpio.h>
24 #include <linux/i2c.h>
25 #include <linux/regulator/consumer.h>
26 #include <linux/delay.h>
27 #include <linux/sysedp.h>
28 #include <linux/input.h>
29 #include <linux/tegra-pmc.h>
30 #ifdef CONFIG_SWITCH
31 #include <linux/switch.h>
32 #endif
33 #include <linux/pm_runtime.h>
34 #include <mach/tegra_asoc_pdata.h>
35 #include <mach/tegra_rt5640_pdata.h>
36
37 #include <sound/core.h>
38 #include <sound/jack.h>
39 #include <sound/pcm.h>
40 #include <sound/pcm_params.h>
41 #include <sound/soc.h>
42
43 #include "tegra_asoc_utils_alt.h"
44 #include "tegra_asoc_machine_alt.h"
45
46 #include "../codecs/audience/es755.h"
47 #include "../codecs/tas2552.h"
48
49 #define DRV_NAME "tegra-snd-t210ref-mobile"
50
51 #define GPIO_SPKR_EN    BIT(0)
52 #define GPIO_HP_MUTE    BIT(1)
53 #define GPIO_INT_MIC_EN BIT(2)
54 #define GPIO_EXT_MIC_EN BIT(3)
55 #define GPIO_HP_DET     BIT(4)
56
57 struct tegra_t210ref {
58         struct tegra_asoc_platform_data *pdata;
59         struct tegra_asoc_audio_clock_info audio_clock;
60         unsigned int num_codec_links;
61         int gpio_requested;
62 #ifdef CONFIG_SWITCH
63         int jack_status;
64 #endif
65         enum snd_soc_bias_level bias_level;
66         int clock_enabled;
67         struct regulator *codec_reg;
68         struct regulator *digital_reg;
69         struct regulator *analog_reg;
70         struct regulator *spk_reg;
71         struct regulator *dmic_reg;
72         struct snd_soc_card *pcard;
73 };
74
75 static struct snd_soc_jack tegra_t210ref_hp_jack;
76
77 static struct snd_soc_jack_gpio tegra_t210ref_hp_jack_gpio = {
78         .name = "headphone detect",
79         .report = SND_JACK_HEADPHONE,
80         .debounce_time = 150,
81         .invert = 1,
82 };
83
84 #ifdef CONFIG_SWITCH
85 static struct switch_dev tegra_t210ref_headset_switch = {
86         .name = "h2w",
87 };
88
89 static int tegra_t210ref_jack_notifier(struct notifier_block *self,
90                               unsigned long action, void *dev)
91 {
92         struct snd_soc_jack *jack = dev;
93         struct snd_soc_codec *codec = jack->codec;
94         struct snd_soc_card *card = codec->card;
95         struct tegra_t210ref *machine = snd_soc_card_get_drvdata(card);
96         enum headset_state state = BIT_NO_HEADSET;
97         static bool button_pressed;
98
99         if (button_pressed) {
100                 button_pressed = false;
101                 return NOTIFY_OK;
102         }
103
104         if (action & (SND_JACK_BTN_0 | SND_JACK_BTN_1 | SND_JACK_BTN_2)) {
105                 button_pressed = true;
106                 return NOTIFY_OK;
107         }
108
109         if (jack == &tegra_t210ref_hp_jack) {
110                 machine->jack_status &= ~SND_JACK_HEADPHONE;
111                 machine->jack_status &= ~SND_JACK_MICROPHONE;
112                 machine->jack_status |= (action & SND_JACK_HEADSET);
113         }
114
115         switch (machine->jack_status) {
116         case SND_JACK_HEADPHONE:
117                 state = BIT_HEADSET_NO_MIC;
118                 break;
119         case SND_JACK_HEADSET:
120                 state = BIT_HEADSET;
121                 break;
122         case SND_JACK_MICROPHONE:
123                 /* mic: would not report */
124         default:
125                 state = BIT_NO_HEADSET;
126         }
127
128         switch_set_state(&tegra_t210ref_headset_switch, state);
129
130         return NOTIFY_OK;
131 }
132
133 static struct notifier_block tegra_t210ref_jack_detect_nb = {
134         .notifier_call = tegra_t210ref_jack_notifier,
135 };
136 #else
137 static struct snd_soc_jack_pin tegra_t210ref_hp_jack_pins[] = {
138         {
139                 .pin = "Headphone Jack",
140                 .mask = SND_JACK_HEADPHONE,
141         },
142 };
143 #endif
144
145 static int tegra_t210ref_dai_init(struct snd_soc_pcm_runtime *rtd,
146                                         int rate,
147                                         int channels,
148                                         u64 formats)
149 {
150         struct snd_soc_dai *codec_dai = rtd->codec_dai;
151         struct snd_soc_codec *codec = codec_dai->codec;
152         struct snd_soc_card *card = codec->card;
153         struct device_node *np = card->dev->of_node;
154         struct tegra_t210ref *machine = snd_soc_card_get_drvdata(card);
155         struct snd_soc_pcm_stream *dai_params;
156         unsigned int idx, mclk, clk_out_rate;
157         int err;
158
159         switch (rate) {
160         case 11025:
161         case 22050:
162         case 44100:
163         case 88200:
164         case 176000:
165                 clk_out_rate = 19200000; /* Codec rate */
166                 mclk = 11289600 * 2; /* PLL_A rate */
167                 break;
168         case 8000:
169         case 16000:
170         case 32000:
171         case 48000:
172         case 64000:
173         case 96000:
174         case 192000:
175         default:
176                 clk_out_rate = 19200000;
177                 mclk = 12288000 * 2;
178                 break;
179         }
180
181         pr_info("Setting pll_a = %d Hz clk_out = %d Hz\n", mclk, clk_out_rate);
182         err = tegra_alt_asoc_utils_set_rate(&machine->audio_clock,
183                                 rate, mclk, clk_out_rate);
184         if (err < 0) {
185                 dev_err(card->dev, "Can't configure clocks\n");
186                 return err;
187         }
188
189         if (!of_device_is_compatible(np,
190           "nvidia,tegra-audio-t210ref-mobile-foster")) {
191                 idx = tegra_machine_get_codec_dai_link_idx("earSmart-playback");
192                 /* check if idx has valid number */
193                 if (idx == -EINVAL)
194                         return idx;
195
196                 dai_params =
197                   (struct snd_soc_pcm_stream *)card->rtd[idx].dai_link->params;
198
199                 /* update link_param to update hw_param for DAPM */
200                 dai_params->rate_min = rate;
201                 dai_params->channels_min = channels;
202                 dai_params->formats = formats;
203
204                 err = snd_soc_dai_set_bclk_ratio(card->rtd[idx].cpu_dai,
205                         tegra_machine_get_bclk_ratio(&card->rtd[idx]));
206                 if (err < 0) {
207                         dev_err(card->dev, "Can't set cpu dai bclk ratio\n");
208                         return err;
209                 }
210         }
211
212         idx = tegra_machine_get_codec_dai_link_idx("spdif-dit-1");
213         if (idx != -EINVAL) {
214                 err = snd_soc_dai_set_bclk_ratio(card->rtd[idx].cpu_dai,
215                         tegra_machine_get_bclk_ratio(&card->rtd[idx]));
216                 if (err < 0) {
217                         dev_err(card->dev, "Can't set cpu dai bclk ratio\n");
218                         return err;
219                 }
220
221                 err = snd_soc_dai_set_tdm_slot(card->rtd[idx].cpu_dai,
222                         (1 << channels) - 1, (1 << channels) - 1, 0, 0);
223                 if (err < 0) {
224                         dev_err(card->dev, "Can't set cpu dai slot ctrl\n");
225                         return err;
226                 }
227         }
228
229         return 0;
230 }
231
232 static int tegra_t210ref_hw_params(struct snd_pcm_substream *substream,
233                                         struct snd_pcm_hw_params *params)
234 {
235         struct snd_soc_pcm_runtime *rtd = substream->private_data;
236         struct snd_soc_dai *codec_dai = rtd->codec_dai;
237         struct snd_soc_codec *codec = codec_dai->codec;
238         struct snd_soc_card *card = codec->card;
239         int err;
240
241         err = tegra_t210ref_dai_init(rtd, params_rate(params),
242                         params_channels(params),
243                         (1ULL << (params_format(params))));
244         if (err < 0) {
245                 dev_err(card->dev, "Failed dai init\n");
246                 return err;
247         }
248
249         return 0;
250 }
251
252 static int tegra_t210ref_compr_set_params(struct snd_compr_stream *cstream)
253 {
254         struct snd_soc_pcm_runtime *rtd = cstream->private_data;
255         struct snd_soc_dai *codec_dai = rtd->codec_dai;
256         struct snd_soc_codec *codec = codec_dai->codec;
257         struct snd_soc_card *card = codec->card;
258         struct snd_soc_platform *platform = rtd->platform;
259         struct snd_codec codec_params;
260         int srate;
261         int err;
262
263         if (platform->driver->compr_ops &&
264                 platform->driver->compr_ops->get_params) {
265                 err = platform->driver->compr_ops->get_params(cstream,
266                         &codec_params);
267                 if (err < 0) {
268                         dev_err(card->dev, "Failed to get compr params\n");
269                         return err;
270                 }
271         } else {
272                 dev_err(card->dev, "compr ops not set\n");
273                 return -EINVAL;
274         }
275
276         /* TODO: Add SRC in offload path */
277         srate = 48000;
278
279         err = tegra_t210ref_dai_init(rtd, srate, codec_params.ch_out,
280                         SNDRV_PCM_FMTBIT_S16_LE);
281         if (err < 0) {
282                 dev_err(card->dev, "Failed dai init\n");
283                 return err;
284         }
285
286         return 0;
287 }
288
289 static int tegra_t210ref_init(struct snd_soc_pcm_runtime *rtd)
290 {
291         struct snd_soc_dai *codec_dai = rtd->codec_dai;
292         struct snd_soc_codec *codec = codec_dai->codec;
293         struct snd_soc_card *card = codec->card;
294         struct tegra_t210ref *machine = snd_soc_card_get_drvdata(card);
295         struct tegra_asoc_platform_data *pdata = machine->pdata;
296         struct snd_soc_pcm_stream *dai_params =
297                 (struct snd_soc_pcm_stream *)rtd->dai_link->params;
298         unsigned int srate;
299         int err;
300
301         srate = dai_params->rate_min;
302
303         err = tegra_alt_asoc_utils_set_extern_parent(&machine->audio_clock,
304                                                         "clk_m");
305         if (err < 0) {
306                 dev_err(card->dev, "Failed to set extern clk parent\n");
307                 return err;
308         }
309
310         if (gpio_is_valid(pdata->gpio_hp_det)) {
311                 tegra_t210ref_hp_jack_gpio.gpio = pdata->gpio_hp_det;
312                 tegra_t210ref_hp_jack_gpio.invert =
313                         !pdata->gpio_hp_det_active_high;
314                 err = snd_soc_jack_new(codec, "Headphone Jack",
315                                (SND_JACK_HEADSET | SND_JACK_BTN_0 |
316                                SND_JACK_BTN_1 | SND_JACK_BTN_2),
317                                &tegra_t210ref_hp_jack);
318                 if (err) {
319                         pr_err("failed to create a jack for es755\n");
320                         return err;
321                 }
322
323                 err = snd_jack_set_key(tegra_t210ref_hp_jack.jack,
324                                 SND_JACK_BTN_0, KEY_MEDIA);
325                 if (err < 0)
326                         pr_err("Failed to set KEY_MEDIA: %d\n", err);
327
328                 err = snd_jack_set_key(tegra_t210ref_hp_jack.jack,
329                                 SND_JACK_BTN_1, KEY_VOLUMEUP);
330                 if (err < 0)
331                         pr_err("Failed to set KEY_VOLUMEUP: %d\n", err);
332
333                 err = snd_jack_set_key(tegra_t210ref_hp_jack.jack,
334                                 SND_JACK_BTN_2, KEY_VOLUMEDOWN);
335                 if (err < 0)
336                         pr_err("Failed to set KEY_VOLUMEDOWN: %d\n", err);
337 #ifdef CONFIG_SWITCH
338                 snd_soc_jack_notifier_register(&tegra_t210ref_hp_jack,
339                                                 &tegra_t210ref_jack_detect_nb);
340 #else /* gpio based headset detection */
341                 snd_soc_jack_add_pins(&tegra_es755_hp_jack,
342                                         ARRAY_SIZE(tegra_es755_hs_jack_pins),
343                                         tegra_es755_hs_jack_pins);
344 #endif
345                 snd_soc_jack_add_gpios(&tegra_t210ref_hp_jack,
346                                         1, &tegra_t210ref_hp_jack_gpio);
347                 machine->gpio_requested |= GPIO_HP_DET;
348
349                 es755_detect(codec, &tegra_t210ref_hp_jack);
350         }
351
352         return 0;
353 }
354
355 static int tegra_t210ref_sfc_init(struct snd_soc_pcm_runtime *rtd)
356 {
357         struct snd_soc_dai *codec_dai = rtd->codec_dai;
358         unsigned int in_srate, out_srate;
359         int err;
360
361         in_srate = 48000;
362         out_srate = 8000;
363
364         err = snd_soc_dai_set_sysclk(codec_dai, 0, out_srate,
365                                         SND_SOC_CLOCK_OUT);
366         err = snd_soc_dai_set_sysclk(codec_dai, 0, in_srate,
367                                         SND_SOC_CLOCK_IN);
368
369         return 0;
370 }
371
372 static int tegra_es755_startup(struct snd_pcm_substream *substream)
373 {
374         escore_pm_get_sync();
375         return 0;
376 }
377
378 static void tegra_es755_shutdown(struct snd_pcm_substream *substream)
379 {
380         escore_pm_put_autosuspend();
381 }
382
383 static int tegra_es755_startup_compr(struct snd_compr_stream *cstream)
384 {
385         escore_pm_get_sync();
386         return 0;
387 }
388
389 static void tegra_es755_shutdown_compr(struct snd_compr_stream *cstream)
390 {
391         escore_pm_put_autosuspend();
392 }
393
394 static struct snd_soc_ops tegra_t210ref_ops = {
395         .hw_params = tegra_t210ref_hw_params,
396         .startup = tegra_es755_startup,
397         .shutdown = tegra_es755_shutdown,
398 };
399
400 static struct snd_soc_compr_ops tegra_t210ref_compr_ops = {
401         .set_params = tegra_t210ref_compr_set_params,
402         .startup = tegra_es755_startup_compr,
403         .shutdown = tegra_es755_shutdown_compr,
404 };
405
406 static const struct snd_soc_dapm_widget tegra_t210ref_dapm_widgets[] = {
407         SND_SOC_DAPM_HP("y Headphone", NULL),
408         SND_SOC_DAPM_MIC("y Mic", NULL),
409 };
410
411 static int tegra_t210ref_suspend_pre(struct snd_soc_card *card)
412 {
413         struct snd_soc_jack_gpio *gpio = &tegra_t210ref_hp_jack_gpio;
414         unsigned int idx;
415
416         /* DAPM dai link stream work for non pcm links */
417         for (idx = 0; idx < card->num_rtd; idx++) {
418                 if (card->rtd[idx].dai_link->params)
419                         INIT_DELAYED_WORK(&card->rtd[idx].delayed_work, NULL);
420         }
421
422         if (gpio_is_valid(gpio->gpio))
423                 disable_irq(gpio_to_irq(gpio->gpio));
424
425         return 0;
426 }
427
428 static int tegra_t210ref_suspend_post(struct snd_soc_card *card)
429 {
430         struct tegra_t210ref *machine = snd_soc_card_get_drvdata(card);
431
432         if (machine->clock_enabled) {
433                 machine->clock_enabled = 0;
434                 tegra_alt_asoc_utils_clk_disable(&machine->audio_clock);
435         }
436
437         return 0;
438 }
439
440 static int tegra_t210ref_resume_pre(struct snd_soc_card *card)
441 {
442         int val;
443         struct snd_soc_jack_gpio *gpio = &tegra_t210ref_hp_jack_gpio;
444         struct tegra_t210ref *machine = snd_soc_card_get_drvdata(card);
445
446         if (gpio_is_valid(gpio->gpio)) {
447                 val = gpio_get_value(gpio->gpio);
448                 val = gpio->invert ? !val : val;
449                 snd_soc_jack_report(gpio->jack, val, gpio->report);
450                 enable_irq(gpio_to_irq(gpio->gpio));
451         }
452
453         if (!machine->clock_enabled) {
454                 machine->clock_enabled = 1;
455                 tegra_alt_asoc_utils_clk_enable(&machine->audio_clock);
456         }
457
458         return 0;
459 }
460
461 static const struct snd_soc_dapm_route tegra_t210ref_audio_map[] = {
462 };
463
464 static int tegra_t210ref_remove(struct snd_soc_card *card)
465 {
466         return 0;
467 }
468
469 static struct snd_soc_card snd_soc_tegra_t210ref = {
470         .name = "tegra-t210ref",
471         .owner = THIS_MODULE,
472         .remove = tegra_t210ref_remove,
473         .suspend_post = tegra_t210ref_suspend_post,
474         .suspend_pre = tegra_t210ref_suspend_pre,
475         .resume_pre = tegra_t210ref_resume_pre,
476         .dapm_widgets = tegra_t210ref_dapm_widgets,
477         .num_dapm_widgets = ARRAY_SIZE(tegra_t210ref_dapm_widgets),
478         .fully_routed = true,
479 };
480
481 static int tegra_t210ref_driver_probe(struct platform_device *pdev)
482 {
483         struct device_node *np = pdev->dev.of_node;
484         struct snd_soc_card *card = &snd_soc_tegra_t210ref;
485         struct tegra_t210ref *machine;
486         struct snd_soc_dai_link *tegra_machine_dai_links = NULL;
487         struct snd_soc_dai_link *tegra_t210ref_codec_links = NULL;
488         struct snd_soc_codec_conf *tegra_machine_codec_conf = NULL;
489         struct snd_soc_codec_conf *tegra_t210ref_codec_conf = NULL;
490         struct tegra_asoc_platform_data *pdata = NULL;
491         int ret = 0, i;
492
493         if (!np) {
494                 dev_err(&pdev->dev, "No device tree node for t210ref driver");
495                 return -ENODEV;
496         }
497
498         if (!of_device_is_compatible(np,
499           "nvidia,tegra-audio-t210ref-mobile-foster")) {
500                 if (escore_is_probe_error()) {
501                         dev_err(&pdev->dev, "No ES755 CODEC found");
502                         return -ENODEV;
503                 }
504         }
505
506         machine = devm_kzalloc(&pdev->dev, sizeof(struct tegra_t210ref),
507                                GFP_KERNEL);
508         if (!machine) {
509                 dev_err(&pdev->dev, "Can't allocate tegra_t210ref struct\n");
510                 ret = -ENOMEM;
511                 goto err;
512         }
513
514         pdata = devm_kzalloc(&pdev->dev,
515                                 sizeof(struct tegra_asoc_platform_data),
516                                 GFP_KERNEL);
517         if (!pdata) {
518                 dev_err(&pdev->dev,
519                         "Can't allocate tegra_asoc_platform_data struct\n");
520                 goto err;
521         }
522
523         card->dev = &pdev->dev;
524         platform_set_drvdata(pdev, card);
525         snd_soc_card_set_drvdata(card, machine);
526
527         ret = snd_soc_of_parse_card_name(card, "nvidia,model");
528         if (ret)
529                 goto err;
530
531         ret = snd_soc_of_parse_audio_routing(card,
532                                 "nvidia,audio-routing");
533         if (ret)
534                 goto err;
535
536         /* set new codec links and conf */
537         tegra_t210ref_codec_links = tegra_machine_new_codec_links(pdev,
538                 tegra_t210ref_codec_links,
539                 &machine->num_codec_links);
540         if (!tegra_t210ref_codec_links)
541                 goto err_alloc_dai_link;
542
543         tegra_t210ref_codec_conf = tegra_machine_new_codec_conf(pdev,
544                 tegra_t210ref_codec_conf,
545                 &machine->num_codec_links);
546         if (!tegra_t210ref_codec_conf)
547                 goto err_alloc_dai_link;
548
549
550         /* get the xbar dai link/codec conf structure */
551         tegra_machine_dai_links = tegra_machine_get_dai_link();
552         if (!tegra_machine_dai_links)
553                 goto err_alloc_dai_link;
554         tegra_machine_codec_conf = tegra_machine_get_codec_conf();
555         if (!tegra_machine_codec_conf)
556                 goto err_alloc_dai_link;
557
558
559         /* set ADMAIF dai_ops */
560         for (i = TEGRA210_DAI_LINK_ADMAIF1;
561                 i <= TEGRA210_DAI_LINK_ADMAIF10; i++)
562                 tegra_machine_set_dai_ops(i, &tegra_t210ref_ops);
563
564
565         /* set sfc dai_init */
566         tegra_machine_set_dai_init(TEGRA210_DAI_LINK_SFC1_RX,
567                 &tegra_t210ref_sfc_init);
568
569         /* set ADSP PCM */
570         tegra_machine_set_dai_ops(TEGRA210_DAI_LINK_ADSP_PCM,
571                         &tegra_t210ref_ops);
572
573         /* set ADSP COMPR */
574         for (i = TEGRA210_DAI_LINK_ADSP_COMPR1;
575                 i <= TEGRA210_DAI_LINK_ADSP_COMPR2; i++) {
576                 tegra_machine_set_dai_compr_ops(i,
577                         &tegra_t210ref_compr_ops);
578         }
579
580         pdata->gpio_hp_det = of_get_named_gpio(np,
581                                         "nvidia,hp-det-gpios", 0);
582         if (pdata->gpio_hp_det < 0)
583                 dev_warn(&pdev->dev, "Failed to get HP Det GPIO\n");
584
585         pdata->gpio_codec1 = pdata->gpio_codec2 = pdata->gpio_codec3 =
586         pdata->gpio_spkr_en = pdata->gpio_hp_mute =
587         pdata->gpio_int_mic_en = pdata->gpio_ext_mic_en =
588         pdata->gpio_ldo1_en =  -1;
589
590                 /* set codec init */
591         for (i = 0; i < machine->num_codec_links; i++) {
592                 if (tegra_t210ref_codec_links[i].name) {
593                         if (strstr(tegra_t210ref_codec_links[i]
594                                 .name, "earSmart-playback"))
595                                 tegra_t210ref_codec_links[i].init =
596                                                 tegra_t210ref_init;
597
598                 }
599         }
600
601         /* append t210ref specific dai_links */
602         card->num_links =
603                 tegra_machine_append_dai_link(tegra_t210ref_codec_links,
604                         2 * machine->num_codec_links);
605         tegra_machine_dai_links = tegra_machine_get_dai_link();
606         card->dai_link = tegra_machine_dai_links;
607
608         /* append t210ref specific codec_conf */
609         card->num_configs =
610                 tegra_machine_append_codec_conf(tegra_t210ref_codec_conf,
611                         machine->num_codec_links);
612         tegra_machine_codec_conf = tegra_machine_get_codec_conf();
613         card->codec_conf = tegra_machine_codec_conf;
614
615 #ifdef CONFIG_SWITCH
616         /* Addd h2w swith class support */
617         ret = tegra_alt_asoc_switch_register(&tegra_t210ref_headset_switch);
618         if (ret < 0)
619                 goto err_alloc_dai_link;
620 #endif
621         /* 1.8V VDDIO_AUDIO_HV_BIAS/HV DAP regulator enable */
622         pwr_detect_bit_write(AUDIO_HV_PWR_DET, false);
623
624         /*
625         *digital_reg - provided the digital power for the codec and must be
626         *ON always
627         */
628         machine->digital_reg = regulator_get(&pdev->dev, "dbvdd");
629         if (IS_ERR(machine->digital_reg))
630                 machine->digital_reg = 0;
631         else
632                 ret = regulator_enable(machine->digital_reg);
633
634         /*
635         *analog_reg - provided the analog power for the codec and must be
636         *ON always
637         */
638         machine->analog_reg = regulator_get(&pdev->dev, "avdd");
639         if (IS_ERR(machine->analog_reg))
640                 machine->analog_reg = 0;
641         else
642                 ret = regulator_enable(machine->analog_reg);
643
644         /*
645         *spk_reg - provided the speaker power and can be turned ON
646         *on need basis, when required
647         */
648         machine->spk_reg = regulator_get(&pdev->dev, "spkvdd");
649         if (IS_ERR(machine->spk_reg))
650                 machine->spk_reg = 0;
651
652         /*
653         *dmic_reg - provided the DMIC power and can be turned ON
654         *on need basis, when required
655         */
656         machine->dmic_reg = regulator_get(&pdev->dev, "dmicvdd");
657         if (IS_ERR(machine->dmic_reg))
658                 machine->dmic_reg = 0;
659
660         machine->pdata = pdata;
661         machine->pcard = card;
662         machine->clock_enabled = 1;
663
664         ret = tegra_alt_asoc_utils_init(&machine->audio_clock,
665                                         &pdev->dev,
666                                         card);
667         if (ret)
668                 goto err_switch_unregister;
669
670         ret = snd_soc_register_card(card);
671         if (ret) {
672                 dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n",
673                         ret);
674                 goto err_fini_utils;
675         }
676
677         return 0;
678
679 err_fini_utils:
680         tegra_alt_asoc_utils_fini(&machine->audio_clock);
681 err_switch_unregister:
682 #ifdef CONFIG_SWITCH
683         tegra_alt_asoc_switch_unregister(&tegra_t210ref_headset_switch);
684 #endif
685         if (machine->gpio_requested & GPIO_HP_DET)
686                 snd_soc_jack_free_gpios(&tegra_t210ref_hp_jack,
687                                         1,
688                                         &tegra_t210ref_hp_jack_gpio);
689
690         if (machine->digital_reg) {
691                 regulator_disable(machine->digital_reg);
692                 regulator_put(machine->digital_reg);
693         }
694         if (machine->analog_reg) {
695                 regulator_disable(machine->analog_reg);
696                 regulator_put(machine->analog_reg);
697         }
698         if (machine->spk_reg)
699                 regulator_put(machine->spk_reg);
700
701         if (machine->dmic_reg)
702                 regulator_put(machine->dmic_reg);
703         if (machine->codec_reg) {
704                 regulator_disable(machine->codec_reg);
705                 regulator_put(machine->codec_reg);
706         }
707 err_alloc_dai_link:
708         tegra_machine_remove_extra_mem_alloc(machine->num_codec_links);
709         tegra_machine_remove_dai_link();
710         tegra_machine_remove_codec_conf();
711 err:
712         return ret;
713 }
714
715 static int tegra_t210ref_driver_remove(struct platform_device *pdev)
716 {
717         struct snd_soc_card *card = platform_get_drvdata(pdev);
718         struct tegra_t210ref *machine = snd_soc_card_get_drvdata(card);
719
720         if (machine->gpio_requested & GPIO_HP_DET)
721                 snd_soc_jack_free_gpios(&tegra_t210ref_hp_jack,
722                                         1,
723                                         &tegra_t210ref_hp_jack_gpio);
724
725         if (machine->digital_reg) {
726                 regulator_disable(machine->digital_reg);
727                 regulator_put(machine->digital_reg);
728         }
729         if (machine->analog_reg) {
730                 regulator_disable(machine->analog_reg);
731                 regulator_put(machine->analog_reg);
732         }
733         if (machine->spk_reg)
734                 regulator_put(machine->spk_reg);
735
736         if (machine->dmic_reg)
737                 regulator_put(machine->dmic_reg);
738         if (machine->codec_reg) {
739                 regulator_disable(machine->codec_reg);
740                 regulator_put(machine->codec_reg);
741         }
742
743         snd_soc_unregister_card(card);
744
745         tegra_machine_remove_extra_mem_alloc(machine->num_codec_links);
746         tegra_machine_remove_dai_link();
747         tegra_machine_remove_codec_conf();
748         tegra_alt_asoc_utils_fini(&machine->audio_clock);
749
750 #ifdef CONFIG_SWITCH
751         tegra_alt_asoc_switch_unregister(&tegra_t210ref_headset_switch);
752 #endif
753
754         return 0;
755 }
756
757 static const struct of_device_id tegra_t210ref_of_match[] = {
758         { .compatible = "nvidia,tegra-audio-t210ref-mobile-es755", },
759         { .compatible = "nvidia,tegra-audio-t210ref-mobile-foster", },
760         {},
761 };
762
763 static struct platform_driver tegra_t210ref_driver = {
764         .driver = {
765                 .name = DRV_NAME,
766                 .owner = THIS_MODULE,
767                 .pm = &snd_soc_pm_ops,
768                 .of_match_table = tegra_t210ref_of_match,
769         },
770         .probe = tegra_t210ref_driver_probe,
771         .remove = tegra_t210ref_driver_remove,
772 };
773 module_platform_driver(tegra_t210ref_driver);
774
775 MODULE_AUTHOR("Dara Ramesh <dramesh@nvidia.com>");
776 MODULE_DESCRIPTION("Tegra+t210ref machine ASoC driver");
777 MODULE_LICENSE("GPL");
778 MODULE_ALIAS("platform:" DRV_NAME);
779 MODULE_DEVICE_TABLE(of, tegra_t210ref_of_match);