e2ce99d6d553e896868886373d4a507d6de1274e
[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         return 0;
213 }
214
215 static int tegra_t210ref_hw_params(struct snd_pcm_substream *substream,
216                                         struct snd_pcm_hw_params *params)
217 {
218         struct snd_soc_pcm_runtime *rtd = substream->private_data;
219         struct snd_soc_dai *codec_dai = rtd->codec_dai;
220         struct snd_soc_codec *codec = codec_dai->codec;
221         struct snd_soc_card *card = codec->card;
222         int err;
223
224         err = tegra_t210ref_dai_init(rtd, params_rate(params),
225                         params_channels(params),
226                         (1ULL << (params_format(params))));
227         if (err < 0) {
228                 dev_err(card->dev, "Failed dai init\n");
229                 return err;
230         }
231
232         return 0;
233 }
234
235 static int tegra_t210ref_compr_set_params(struct snd_compr_stream *cstream)
236 {
237         struct snd_soc_pcm_runtime *rtd = cstream->private_data;
238         struct snd_soc_dai *codec_dai = rtd->codec_dai;
239         struct snd_soc_codec *codec = codec_dai->codec;
240         struct snd_soc_card *card = codec->card;
241         struct snd_soc_platform *platform = rtd->platform;
242         struct snd_codec codec_params;
243         int srate;
244         int err;
245
246         if (platform->driver->compr_ops &&
247                 platform->driver->compr_ops->get_params) {
248                 err = platform->driver->compr_ops->get_params(cstream,
249                         &codec_params);
250                 if (err < 0) {
251                         dev_err(card->dev, "Failed to get compr params\n");
252                         return err;
253                 }
254         } else {
255                 dev_err(card->dev, "compr ops not set\n");
256                 return -EINVAL;
257         }
258
259         /* TODO: Add SRC in offload path */
260         srate = 48000;
261
262         err = tegra_t210ref_dai_init(rtd, srate, codec_params.ch_out,
263                         SNDRV_PCM_FMTBIT_S16_LE);
264         if (err < 0) {
265                 dev_err(card->dev, "Failed dai init\n");
266                 return err;
267         }
268
269         return 0;
270 }
271
272 static int tegra_t210ref_init(struct snd_soc_pcm_runtime *rtd)
273 {
274         struct snd_soc_dai *codec_dai = rtd->codec_dai;
275         struct snd_soc_codec *codec = codec_dai->codec;
276         struct snd_soc_card *card = codec->card;
277         struct tegra_t210ref *machine = snd_soc_card_get_drvdata(card);
278         struct tegra_asoc_platform_data *pdata = machine->pdata;
279         struct snd_soc_pcm_stream *dai_params =
280                 (struct snd_soc_pcm_stream *)rtd->dai_link->params;
281         unsigned int srate;
282         int err;
283
284         srate = dai_params->rate_min;
285
286         err = tegra_alt_asoc_utils_set_extern_parent(&machine->audio_clock,
287                                                         "clk_m");
288         if (err < 0) {
289                 dev_err(card->dev, "Failed to set extern clk parent\n");
290                 return err;
291         }
292
293         if (gpio_is_valid(pdata->gpio_hp_det)) {
294                 tegra_t210ref_hp_jack_gpio.gpio = pdata->gpio_hp_det;
295                 tegra_t210ref_hp_jack_gpio.invert =
296                         !pdata->gpio_hp_det_active_high;
297                 err = snd_soc_jack_new(codec, "Headphone Jack",
298                                (SND_JACK_HEADSET | SND_JACK_BTN_0 |
299                                SND_JACK_BTN_1 | SND_JACK_BTN_2),
300                                &tegra_t210ref_hp_jack);
301                 if (err) {
302                         pr_err("failed to create a jack for es755\n");
303                         return err;
304                 }
305
306                 err = snd_jack_set_key(tegra_t210ref_hp_jack.jack,
307                                 SND_JACK_BTN_0, KEY_MEDIA);
308                 if (err < 0)
309                         pr_err("Failed to set KEY_MEDIA: %d\n", err);
310
311                 err = snd_jack_set_key(tegra_t210ref_hp_jack.jack,
312                                 SND_JACK_BTN_1, KEY_VOLUMEUP);
313                 if (err < 0)
314                         pr_err("Failed to set KEY_VOLUMEUP: %d\n", err);
315
316                 err = snd_jack_set_key(tegra_t210ref_hp_jack.jack,
317                                 SND_JACK_BTN_2, KEY_VOLUMEDOWN);
318                 if (err < 0)
319                         pr_err("Failed to set KEY_VOLUMEDOWN: %d\n", err);
320 #ifdef CONFIG_SWITCH
321                 snd_soc_jack_notifier_register(&tegra_t210ref_hp_jack,
322                                                 &tegra_t210ref_jack_detect_nb);
323 #else /* gpio based headset detection */
324                 snd_soc_jack_add_pins(&tegra_es755_hp_jack,
325                                         ARRAY_SIZE(tegra_es755_hs_jack_pins),
326                                         tegra_es755_hs_jack_pins);
327 #endif
328                 snd_soc_jack_add_gpios(&tegra_t210ref_hp_jack,
329                                         1, &tegra_t210ref_hp_jack_gpio);
330                 machine->gpio_requested |= GPIO_HP_DET;
331
332                 es755_detect(codec, &tegra_t210ref_hp_jack);
333         }
334
335         return 0;
336 }
337
338 static int tegra_t210ref_sfc_init(struct snd_soc_pcm_runtime *rtd)
339 {
340         struct snd_soc_dai *codec_dai = rtd->codec_dai;
341         unsigned int in_srate, out_srate;
342         int err;
343
344         in_srate = 48000;
345         out_srate = 8000;
346
347         err = snd_soc_dai_set_sysclk(codec_dai, 0, out_srate,
348                                         SND_SOC_CLOCK_OUT);
349         err = snd_soc_dai_set_sysclk(codec_dai, 0, in_srate,
350                                         SND_SOC_CLOCK_IN);
351
352         return 0;
353 }
354
355 static int tegra_es755_startup(struct snd_pcm_substream *substream)
356 {
357         escore_pm_get_sync();
358         return 0;
359 }
360
361 static void tegra_es755_shutdown(struct snd_pcm_substream *substream)
362 {
363         escore_pm_put_autosuspend();
364 }
365
366 static int tegra_es755_startup_compr(struct snd_compr_stream *cstream)
367 {
368         escore_pm_get_sync();
369         return 0;
370 }
371
372 static void tegra_es755_shutdown_compr(struct snd_compr_stream *cstream)
373 {
374         escore_pm_put_autosuspend();
375 }
376
377 static struct snd_soc_ops tegra_t210ref_ops = {
378         .hw_params = tegra_t210ref_hw_params,
379         .startup = tegra_es755_startup,
380         .shutdown = tegra_es755_shutdown,
381 };
382
383 static struct snd_soc_compr_ops tegra_t210ref_compr_ops = {
384         .set_params = tegra_t210ref_compr_set_params,
385         .startup = tegra_es755_startup_compr,
386         .shutdown = tegra_es755_shutdown_compr,
387 };
388
389 static const struct snd_soc_dapm_widget tegra_t210ref_dapm_widgets[] = {
390         SND_SOC_DAPM_HP("y Headphone", NULL),
391         SND_SOC_DAPM_MIC("y Mic", NULL),
392 };
393
394 static int tegra_t210ref_suspend_pre(struct snd_soc_card *card)
395 {
396         struct snd_soc_jack_gpio *gpio = &tegra_t210ref_hp_jack_gpio;
397         unsigned int idx;
398
399         /* DAPM dai link stream work for non pcm links */
400         for (idx = 0; idx < card->num_rtd; idx++) {
401                 if (card->rtd[idx].dai_link->params)
402                         INIT_DELAYED_WORK(&card->rtd[idx].delayed_work, NULL);
403         }
404
405         if (gpio_is_valid(gpio->gpio))
406                 disable_irq(gpio_to_irq(gpio->gpio));
407
408         return 0;
409 }
410
411 static int tegra_t210ref_suspend_post(struct snd_soc_card *card)
412 {
413         struct tegra_t210ref *machine = snd_soc_card_get_drvdata(card);
414
415         if (machine->clock_enabled) {
416                 machine->clock_enabled = 0;
417                 tegra_alt_asoc_utils_clk_disable(&machine->audio_clock);
418         }
419
420         return 0;
421 }
422
423 static int tegra_t210ref_resume_pre(struct snd_soc_card *card)
424 {
425         int val;
426         struct snd_soc_jack_gpio *gpio = &tegra_t210ref_hp_jack_gpio;
427         struct tegra_t210ref *machine = snd_soc_card_get_drvdata(card);
428
429         if (gpio_is_valid(gpio->gpio)) {
430                 val = gpio_get_value(gpio->gpio);
431                 val = gpio->invert ? !val : val;
432                 snd_soc_jack_report(gpio->jack, val, gpio->report);
433                 enable_irq(gpio_to_irq(gpio->gpio));
434         }
435
436         if (!machine->clock_enabled) {
437                 machine->clock_enabled = 1;
438                 tegra_alt_asoc_utils_clk_enable(&machine->audio_clock);
439         }
440
441         return 0;
442 }
443
444 static const struct snd_soc_dapm_route tegra_t210ref_audio_map[] = {
445 };
446
447 static int tegra_t210ref_remove(struct snd_soc_card *card)
448 {
449         return 0;
450 }
451
452 static struct snd_soc_card snd_soc_tegra_t210ref = {
453         .name = "tegra-t210ref",
454         .owner = THIS_MODULE,
455         .remove = tegra_t210ref_remove,
456         .suspend_post = tegra_t210ref_suspend_post,
457         .suspend_pre = tegra_t210ref_suspend_pre,
458         .resume_pre = tegra_t210ref_resume_pre,
459         .dapm_widgets = tegra_t210ref_dapm_widgets,
460         .num_dapm_widgets = ARRAY_SIZE(tegra_t210ref_dapm_widgets),
461         .fully_routed = true,
462 };
463
464 static int tegra_t210ref_driver_probe(struct platform_device *pdev)
465 {
466         struct device_node *np = pdev->dev.of_node;
467         struct snd_soc_card *card = &snd_soc_tegra_t210ref;
468         struct tegra_t210ref *machine;
469         struct snd_soc_dai_link *tegra_machine_dai_links = NULL;
470         struct snd_soc_dai_link *tegra_t210ref_codec_links = NULL;
471         struct snd_soc_codec_conf *tegra_machine_codec_conf = NULL;
472         struct snd_soc_codec_conf *tegra_t210ref_codec_conf = NULL;
473         struct tegra_asoc_platform_data *pdata = NULL;
474         int ret = 0, i;
475
476         if (!np) {
477                 dev_err(&pdev->dev, "No device tree node for t210ref driver");
478                 return -ENODEV;
479         }
480
481         if (!of_device_is_compatible(np,
482           "nvidia,tegra-audio-t210ref-mobile-foster")) {
483                 if (escore_is_probe_error()) {
484                         dev_err(&pdev->dev, "No ES755 CODEC found");
485                         return -ENODEV;
486                 }
487         }
488
489         machine = devm_kzalloc(&pdev->dev, sizeof(struct tegra_t210ref),
490                                GFP_KERNEL);
491         if (!machine) {
492                 dev_err(&pdev->dev, "Can't allocate tegra_t210ref struct\n");
493                 ret = -ENOMEM;
494                 goto err;
495         }
496
497         pdata = devm_kzalloc(&pdev->dev,
498                                 sizeof(struct tegra_asoc_platform_data),
499                                 GFP_KERNEL);
500         if (!pdata) {
501                 dev_err(&pdev->dev,
502                         "Can't allocate tegra_asoc_platform_data struct\n");
503                 goto err;
504         }
505
506         card->dev = &pdev->dev;
507         platform_set_drvdata(pdev, card);
508         snd_soc_card_set_drvdata(card, machine);
509
510         ret = snd_soc_of_parse_card_name(card, "nvidia,model");
511         if (ret)
512                 goto err;
513
514         ret = snd_soc_of_parse_audio_routing(card,
515                                 "nvidia,audio-routing");
516         if (ret)
517                 goto err;
518
519         /* set new codec links and conf */
520         tegra_t210ref_codec_links = tegra_machine_new_codec_links(pdev,
521                 tegra_t210ref_codec_links,
522                 &machine->num_codec_links);
523         if (!tegra_t210ref_codec_links)
524                 goto err_alloc_dai_link;
525
526         tegra_t210ref_codec_conf = tegra_machine_new_codec_conf(pdev,
527                 tegra_t210ref_codec_conf,
528                 &machine->num_codec_links);
529         if (!tegra_t210ref_codec_conf)
530                 goto err_alloc_dai_link;
531
532
533         /* get the xbar dai link/codec conf structure */
534         tegra_machine_dai_links = tegra_machine_get_dai_link();
535         if (!tegra_machine_dai_links)
536                 goto err_alloc_dai_link;
537         tegra_machine_codec_conf = tegra_machine_get_codec_conf();
538         if (!tegra_machine_codec_conf)
539                 goto err_alloc_dai_link;
540
541
542         /* set ADMAIF dai_ops */
543         for (i = TEGRA210_DAI_LINK_ADMAIF1;
544                 i <= TEGRA210_DAI_LINK_ADMAIF10; i++)
545                 tegra_machine_set_dai_ops(i, &tegra_t210ref_ops);
546
547
548         /* set sfc dai_init */
549         tegra_machine_set_dai_init(TEGRA210_DAI_LINK_SFC1_RX,
550                 &tegra_t210ref_sfc_init);
551
552         /* set ADSP PCM */
553         tegra_machine_set_dai_ops(TEGRA210_DAI_LINK_ADSP_PCM,
554                         &tegra_t210ref_ops);
555
556         /* set ADSP COMPR */
557         for (i = TEGRA210_DAI_LINK_ADSP_COMPR1;
558                 i <= TEGRA210_DAI_LINK_ADSP_COMPR2; i++) {
559                 tegra_machine_set_dai_compr_ops(i,
560                         &tegra_t210ref_compr_ops);
561         }
562
563         pdata->gpio_hp_det = of_get_named_gpio(np,
564                                         "nvidia,hp-det-gpios", 0);
565         if (pdata->gpio_hp_det < 0)
566                 dev_warn(&pdev->dev, "Failed to get HP Det GPIO\n");
567
568         pdata->gpio_codec1 = pdata->gpio_codec2 = pdata->gpio_codec3 =
569         pdata->gpio_spkr_en = pdata->gpio_hp_mute =
570         pdata->gpio_int_mic_en = pdata->gpio_ext_mic_en =
571         pdata->gpio_ldo1_en =  -1;
572
573                 /* set codec init */
574         for (i = 0; i < machine->num_codec_links; i++) {
575                 if (tegra_t210ref_codec_links[i].name) {
576                         if (strstr(tegra_t210ref_codec_links[i]
577                                 .name, "earSmart-playback"))
578                                 tegra_t210ref_codec_links[i].init =
579                                                 tegra_t210ref_init;
580
581                 }
582         }
583
584         /* append t210ref specific dai_links */
585         card->num_links =
586                 tegra_machine_append_dai_link(tegra_t210ref_codec_links,
587                         2 * machine->num_codec_links);
588         tegra_machine_dai_links = tegra_machine_get_dai_link();
589         card->dai_link = tegra_machine_dai_links;
590
591         /* append t210ref specific codec_conf */
592         card->num_configs =
593                 tegra_machine_append_codec_conf(tegra_t210ref_codec_conf,
594                         machine->num_codec_links);
595         tegra_machine_codec_conf = tegra_machine_get_codec_conf();
596         card->codec_conf = tegra_machine_codec_conf;
597
598 #ifdef CONFIG_SWITCH
599         /* Addd h2w swith class support */
600         ret = tegra_alt_asoc_switch_register(&tegra_t210ref_headset_switch);
601         if (ret < 0)
602                 goto err_alloc_dai_link;
603 #endif
604         /* 1.8V VDDIO_AUDIO_HV_BIAS/HV DAP regulator enable */
605         pwr_detect_bit_write(AUDIO_HV_PWR_DET, false);
606
607         /*
608         *digital_reg - provided the digital power for the codec and must be
609         *ON always
610         */
611         machine->digital_reg = regulator_get(&pdev->dev, "dbvdd");
612         if (IS_ERR(machine->digital_reg))
613                 machine->digital_reg = 0;
614         else
615                 ret = regulator_enable(machine->digital_reg);
616
617         /*
618         *analog_reg - provided the analog power for the codec and must be
619         *ON always
620         */
621         machine->analog_reg = regulator_get(&pdev->dev, "avdd");
622         if (IS_ERR(machine->analog_reg))
623                 machine->analog_reg = 0;
624         else
625                 ret = regulator_enable(machine->analog_reg);
626
627         /*
628         *spk_reg - provided the speaker power and can be turned ON
629         *on need basis, when required
630         */
631         machine->spk_reg = regulator_get(&pdev->dev, "spkvdd");
632         if (IS_ERR(machine->spk_reg))
633                 machine->spk_reg = 0;
634
635         /*
636         *dmic_reg - provided the DMIC power and can be turned ON
637         *on need basis, when required
638         */
639         machine->dmic_reg = regulator_get(&pdev->dev, "dmicvdd");
640         if (IS_ERR(machine->dmic_reg))
641                 machine->dmic_reg = 0;
642
643         machine->pdata = pdata;
644         machine->pcard = card;
645         machine->clock_enabled = 1;
646
647         ret = tegra_alt_asoc_utils_init(&machine->audio_clock,
648                                         &pdev->dev,
649                                         card);
650         if (ret)
651                 goto err_switch_unregister;
652
653         ret = snd_soc_register_card(card);
654         if (ret) {
655                 dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n",
656                         ret);
657                 goto err_fini_utils;
658         }
659
660         return 0;
661
662 err_fini_utils:
663         tegra_alt_asoc_utils_fini(&machine->audio_clock);
664 err_switch_unregister:
665 #ifdef CONFIG_SWITCH
666         tegra_alt_asoc_switch_unregister(&tegra_t210ref_headset_switch);
667 #endif
668         if (machine->gpio_requested & GPIO_HP_DET)
669                 snd_soc_jack_free_gpios(&tegra_t210ref_hp_jack,
670                                         1,
671                                         &tegra_t210ref_hp_jack_gpio);
672
673         if (machine->digital_reg) {
674                 regulator_disable(machine->digital_reg);
675                 regulator_put(machine->digital_reg);
676         }
677         if (machine->analog_reg) {
678                 regulator_disable(machine->analog_reg);
679                 regulator_put(machine->analog_reg);
680         }
681         if (machine->spk_reg)
682                 regulator_put(machine->spk_reg);
683
684         if (machine->dmic_reg)
685                 regulator_put(machine->dmic_reg);
686         if (machine->codec_reg) {
687                 regulator_disable(machine->codec_reg);
688                 regulator_put(machine->codec_reg);
689         }
690 err_alloc_dai_link:
691         tegra_machine_remove_extra_mem_alloc(machine->num_codec_links);
692         tegra_machine_remove_dai_link();
693         tegra_machine_remove_codec_conf();
694 err:
695         return ret;
696 }
697
698 static int tegra_t210ref_driver_remove(struct platform_device *pdev)
699 {
700         struct snd_soc_card *card = platform_get_drvdata(pdev);
701         struct tegra_t210ref *machine = snd_soc_card_get_drvdata(card);
702
703         if (machine->gpio_requested & GPIO_HP_DET)
704                 snd_soc_jack_free_gpios(&tegra_t210ref_hp_jack,
705                                         1,
706                                         &tegra_t210ref_hp_jack_gpio);
707
708         if (machine->digital_reg) {
709                 regulator_disable(machine->digital_reg);
710                 regulator_put(machine->digital_reg);
711         }
712         if (machine->analog_reg) {
713                 regulator_disable(machine->analog_reg);
714                 regulator_put(machine->analog_reg);
715         }
716         if (machine->spk_reg)
717                 regulator_put(machine->spk_reg);
718
719         if (machine->dmic_reg)
720                 regulator_put(machine->dmic_reg);
721         if (machine->codec_reg) {
722                 regulator_disable(machine->codec_reg);
723                 regulator_put(machine->codec_reg);
724         }
725
726         snd_soc_unregister_card(card);
727
728         tegra_machine_remove_extra_mem_alloc(machine->num_codec_links);
729         tegra_machine_remove_dai_link();
730         tegra_machine_remove_codec_conf();
731         tegra_alt_asoc_utils_fini(&machine->audio_clock);
732
733 #ifdef CONFIG_SWITCH
734         tegra_alt_asoc_switch_unregister(&tegra_t210ref_headset_switch);
735 #endif
736
737         return 0;
738 }
739
740 static const struct of_device_id tegra_t210ref_of_match[] = {
741         { .compatible = "nvidia,tegra-audio-t210ref-mobile-es755", },
742         { .compatible = "nvidia,tegra-audio-t210ref-mobile-foster", },
743         {},
744 };
745
746 static struct platform_driver tegra_t210ref_driver = {
747         .driver = {
748                 .name = DRV_NAME,
749                 .owner = THIS_MODULE,
750                 .pm = &snd_soc_pm_ops,
751                 .of_match_table = tegra_t210ref_of_match,
752         },
753         .probe = tegra_t210ref_driver_probe,
754         .remove = tegra_t210ref_driver_remove,
755 };
756 module_platform_driver(tegra_t210ref_driver);
757
758 MODULE_AUTHOR("Dara Ramesh <dramesh@nvidia.com>");
759 MODULE_DESCRIPTION("Tegra+t210ref machine ASoC driver");
760 MODULE_LICENSE("GPL");
761 MODULE_ALIAS("platform:" DRV_NAME);
762 MODULE_DEVICE_TABLE(of, tegra_t210ref_of_match);