6ca6f76c84aa19557d786e27e8dd4ac9d632e926
[linux-2.6.git] / sound / soc / tegra / tegra_rt5640.c
1 /*
2  * tegra_rt5640.c - Tegra machine ASoC driver for boards using ALC5640 codec.
3  *
4  * Author: Johnny Qiu <joqiu@nvidia.com>
5  * Copyright (C) 2011-2012, NVIDIA, Inc.
6  *
7  * Based on code copyright/by:
8  *
9  * Copyright 2007 Wolfson Microelectronics PLC.
10  * Author: Graeme Gregory
11  *         graeme.gregory@wolfsonmicro.com or linux@wolfsonmicro.com
12  *
13  * This program is free software; you can redistribute it and/or
14  * modify it under the terms of the GNU General Public License
15  * version 2 as published by the Free Software Foundation.
16  *
17  * This program is distributed in the hope that it will be useful, but
18  * WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
20  * General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with this program; if not, write to the Free Software
24  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
25  * 02110-1301 USA
26  *
27  */
28
29 #include <asm/mach-types.h>
30
31 #include <linux/module.h>
32 #include <linux/platform_device.h>
33 #include <linux/slab.h>
34 #include <linux/gpio.h>
35 #include <linux/regulator/consumer.h>
36 #ifdef CONFIG_SWITCH
37 #include <linux/switch.h>
38 #endif
39
40 #include <mach/tegra_rt5640_pdata.h>
41
42 #include <sound/core.h>
43 #include <sound/jack.h>
44 #include <sound/pcm.h>
45 #include <sound/pcm_params.h>
46 #include <sound/soc.h>
47
48 #include "../codecs/rt5639.h"
49 #include "../codecs/rt5640.h"
50
51 #include "tegra_pcm.h"
52 #include "tegra_asoc_utils.h"
53
54 #define DRV_NAME "tegra-snd-rt5640"
55
56 #define GPIO_SPKR_EN    BIT(0)
57 #define GPIO_HP_MUTE    BIT(1)
58 #define GPIO_INT_MIC_EN BIT(2)
59 #define GPIO_EXT_MIC_EN BIT(3)
60 #define GPIO_HP_DET     BIT(4)
61
62 struct tegra_rt5640 {
63         struct tegra_asoc_utils_data util_data;
64         struct tegra_rt5640_platform_data *pdata;
65         struct regulator *spk_reg;
66         struct regulator *dmic_reg;
67         struct regulator *cdc_en;
68         int gpio_requested;
69 #ifdef CONFIG_SWITCH
70         int jack_status;
71 #endif
72 };
73
74 static int tegra_rt5640_hw_params(struct snd_pcm_substream *substream,
75                                         struct snd_pcm_hw_params *params)
76 {
77         struct snd_soc_pcm_runtime *rtd = substream->private_data;
78         struct snd_soc_dai *codec_dai = rtd->codec_dai;
79         struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
80         struct snd_soc_codec *codec = rtd->codec;
81         struct snd_soc_card *card = codec->card;
82         struct tegra_rt5640 *machine = snd_soc_card_get_drvdata(card);
83         int srate, mclk, i2s_daifmt;
84         int err;
85
86         srate = params_rate(params);
87         mclk = 256 * srate;
88         err = tegra_asoc_utils_set_rate(&machine->util_data, srate, mclk);
89         if (err < 0) {
90                 if (!(machine->util_data.set_mclk % mclk)) {
91                         mclk = machine->util_data.set_mclk;
92                 } else {
93                         dev_err(card->dev, "Can't configure clocks\n");
94                         return err;
95                 }
96         }
97
98         tegra_asoc_utils_lock_clk_rate(&machine->util_data, 1);
99
100         i2s_daifmt = SND_SOC_DAIFMT_NB_NF |
101                      SND_SOC_DAIFMT_CBS_CFS;
102
103         i2s_daifmt |= SND_SOC_DAIFMT_I2S;
104
105         err = snd_soc_dai_set_fmt(codec_dai, i2s_daifmt);
106         if (err < 0) {
107                 dev_err(card->dev, "codec_dai fmt not set\n");
108                 return err;
109         }
110
111         err = snd_soc_dai_set_fmt(cpu_dai, i2s_daifmt);
112         if (err < 0) {
113                 dev_err(card->dev, "cpu_dai fmt not set\n");
114                 return err;
115         }
116
117         err = snd_soc_dai_set_sysclk(codec_dai, 0, mclk,
118                                         SND_SOC_CLOCK_IN);
119         if (err < 0) {
120                 dev_err(card->dev, "codec_dai clock not set\n");
121                 return err;
122         }
123
124         return 0;
125 }
126
127 static int tegra_bt_sco_hw_params(struct snd_pcm_substream *substream,
128                                         struct snd_pcm_hw_params *params)
129 {
130         struct snd_soc_pcm_runtime *rtd = substream->private_data;
131         struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
132         struct snd_soc_card *card = rtd->card;
133         struct tegra_rt5640 *machine = snd_soc_card_get_drvdata(card);
134         int srate, mclk, min_mclk;
135         int err;
136
137         srate = params_rate(params);
138         switch (srate) {
139         case 11025:
140         case 22050:
141         case 44100:
142         case 88200:
143                 mclk = 11289600;
144                 break;
145         case 8000:
146         case 16000:
147         case 32000:
148         case 48000:
149         case 64000:
150         case 96000:
151                 mclk = 12288000;
152                 break;
153         default:
154                 return -EINVAL;
155         }
156         min_mclk = 64 * srate;
157
158         err = tegra_asoc_utils_set_rate(&machine->util_data, srate, mclk);
159         if (err < 0) {
160                 if (!(machine->util_data.set_mclk % min_mclk))
161                         mclk = machine->util_data.set_mclk;
162                 else {
163                         dev_err(card->dev, "Can't configure clocks\n");
164                         return err;
165                 }
166         }
167
168         tegra_asoc_utils_lock_clk_rate(&machine->util_data, 1);
169
170         err = snd_soc_dai_set_fmt(cpu_dai,
171                                         SND_SOC_DAIFMT_DSP_A |
172                                         SND_SOC_DAIFMT_NB_NF |
173                                         SND_SOC_DAIFMT_CBS_CFS);
174         if (err < 0) {
175                 dev_err(card->dev, "cpu_dai fmt not set\n");
176                 return err;
177         }
178
179         return 0;
180 }
181
182 static int tegra_spdif_hw_params(struct snd_pcm_substream *substream,
183                                         struct snd_pcm_hw_params *params)
184 {
185         struct snd_soc_pcm_runtime *rtd = substream->private_data;
186         struct snd_soc_card *card = rtd->card;
187         struct tegra_rt5640 *machine = snd_soc_card_get_drvdata(card);
188         int srate, mclk, min_mclk;
189         int err;
190
191         srate = params_rate(params);
192         switch (srate) {
193         case 11025:
194         case 22050:
195         case 44100:
196         case 88200:
197                 mclk = 11289600;
198                 break;
199         case 8000:
200         case 16000:
201         case 32000:
202         case 48000:
203         case 64000:
204         case 96000:
205                 mclk = 12288000;
206                 break;
207         default:
208                 return -EINVAL;
209         }
210         min_mclk = 128 * srate;
211
212         err = tegra_asoc_utils_set_rate(&machine->util_data, srate, mclk);
213         if (err < 0) {
214                 if (!(machine->util_data.set_mclk % min_mclk))
215                         mclk = machine->util_data.set_mclk;
216                 else {
217                         dev_err(card->dev, "Can't configure clocks\n");
218                         return err;
219                 }
220         }
221
222         tegra_asoc_utils_lock_clk_rate(&machine->util_data, 1);
223
224         return 0;
225 }
226
227 static int tegra_hw_free(struct snd_pcm_substream *substream)
228 {
229         struct snd_soc_pcm_runtime *rtd = substream->private_data;
230         struct tegra_rt5640 *machine = snd_soc_card_get_drvdata(rtd->card);
231
232         tegra_asoc_utils_lock_clk_rate(&machine->util_data, 0);
233
234         return 0;
235 }
236
237 static struct snd_soc_ops tegra_rt5640_ops = {
238         .hw_params = tegra_rt5640_hw_params,
239         .hw_free = tegra_hw_free,
240 };
241
242 static struct snd_soc_ops tegra_rt5640_bt_sco_ops = {
243         .hw_params = tegra_bt_sco_hw_params,
244         .hw_free = tegra_hw_free,
245 };
246
247 static struct snd_soc_ops tegra_spdif_ops = {
248         .hw_params = tegra_spdif_hw_params,
249         .hw_free = tegra_hw_free,
250 };
251
252 static struct snd_soc_jack tegra_rt5640_hp_jack;
253
254 static struct snd_soc_jack_gpio tegra_rt5640_hp_jack_gpio = {
255         .name = "headphone detect",
256         .report = SND_JACK_HEADPHONE,
257         .debounce_time = 150,
258         .invert = 1,
259 };
260
261 #ifdef CONFIG_SWITCH
262 /* These values are copied from Android WiredAccessoryObserver */
263 enum headset_state {
264         BIT_NO_HEADSET = 0,
265         BIT_HEADSET = (1 << 0),
266         BIT_HEADSET_NO_MIC = (1 << 1),
267 };
268
269 static struct switch_dev tegra_rt5640_headset_switch = {
270         .name = "h2w",
271 };
272
273 static int tegra_rt5640_jack_notifier(struct notifier_block *self,
274                               unsigned long action, void *dev)
275 {
276         struct snd_soc_jack *jack = dev;
277         struct snd_soc_codec *codec = jack->codec;
278         struct snd_soc_card *card = codec->card;
279         struct tegra_rt5640 *machine = snd_soc_card_get_drvdata(card);
280         struct tegra_rt5640_platform_data *pdata = machine->pdata;
281         enum headset_state state = BIT_NO_HEADSET;
282         unsigned char status_jack = 0;
283
284         if (jack == &tegra_rt5640_hp_jack) {
285                 if (action) {
286                         /* Enable ext mic; enable signal is active-low */
287                         gpio_direction_output(pdata->gpio_ext_mic_en, 0);
288                         if (!strncmp(machine->pdata->codec_name, "rt5639", 6))
289                                 status_jack = rt5639_headset_detect(codec, 1);
290                         else if (!strncmp(machine->pdata->codec_name, "rt5640",
291                                                                             6))
292                                 status_jack = rt5640_headset_detect(codec, 1);
293
294                         machine->jack_status &= ~SND_JACK_HEADPHONE;
295                         machine->jack_status &= ~SND_JACK_MICROPHONE;
296                         if (status_jack == RT5639_HEADPHO_DET ||
297                             status_jack == RT5640_HEADPHO_DET)
298                                         machine->jack_status |=
299                                                         SND_JACK_HEADPHONE;
300                         else if (status_jack == RT5639_HEADSET_DET ||
301                                  status_jack == RT5640_HEADSET_DET) {
302                                         machine->jack_status |=
303                                                         SND_JACK_HEADPHONE;
304                                         machine->jack_status |=
305                                                         SND_JACK_MICROPHONE;
306                         }
307                 } else {
308                         /* Disable ext mic; enable signal is active-low */
309                         gpio_direction_output(pdata->gpio_ext_mic_en, 1);
310                         if (!strncmp(machine->pdata->codec_name, "rt5639", 6))
311                                 rt5639_headset_detect(codec, 0);
312                         else if (!strncmp(machine->pdata->codec_name, "rt5640",
313                                                                             6))
314                                 rt5640_headset_detect(codec, 0);
315
316                         machine->jack_status &= ~SND_JACK_HEADPHONE;
317                         machine->jack_status &= ~SND_JACK_MICROPHONE;
318                 }
319         }
320
321         switch (machine->jack_status) {
322         case SND_JACK_HEADPHONE:
323                 state = BIT_HEADSET_NO_MIC;
324                 break;
325         case SND_JACK_HEADSET:
326                 state = BIT_HEADSET;
327                 break;
328         case SND_JACK_MICROPHONE:
329                 /* mic: would not report */
330         default:
331                 state = BIT_NO_HEADSET;
332         }
333
334         switch_set_state(&tegra_rt5640_headset_switch, state);
335
336         return NOTIFY_OK;
337 }
338
339 static struct notifier_block tegra_rt5640_jack_detect_nb = {
340         .notifier_call = tegra_rt5640_jack_notifier,
341 };
342 #else
343 static struct snd_soc_jack_pin tegra_rt5640_hp_jack_pins[] = {
344         {
345                 .pin = "Headphone Jack",
346                 .mask = SND_JACK_HEADPHONE,
347         },
348 };
349
350 #endif
351
352 static int tegra_rt5640_event_int_spk(struct snd_soc_dapm_widget *w,
353                                         struct snd_kcontrol *k, int event)
354 {
355         struct snd_soc_dapm_context *dapm = w->dapm;
356         struct snd_soc_card *card = dapm->card;
357         struct tegra_rt5640 *machine = snd_soc_card_get_drvdata(card);
358         struct tegra_rt5640_platform_data *pdata = machine->pdata;
359
360         if (machine->spk_reg) {
361                 if (SND_SOC_DAPM_EVENT_ON(event))
362                         regulator_enable(machine->spk_reg);
363                 else
364                         regulator_disable(machine->spk_reg);
365         }
366
367         if (!(machine->gpio_requested & GPIO_SPKR_EN))
368                 return 0;
369
370         gpio_set_value_cansleep(pdata->gpio_spkr_en,
371                                 SND_SOC_DAPM_EVENT_ON(event));
372
373         return 0;
374 }
375
376 static int tegra_rt5640_event_hp(struct snd_soc_dapm_widget *w,
377                                         struct snd_kcontrol *k, int event)
378 {
379         struct snd_soc_dapm_context *dapm = w->dapm;
380         struct snd_soc_card *card = dapm->card;
381         struct tegra_rt5640 *machine = snd_soc_card_get_drvdata(card);
382         struct tegra_rt5640_platform_data *pdata = machine->pdata;
383
384         if (!(machine->gpio_requested & GPIO_HP_MUTE))
385                 return 0;
386
387         gpio_set_value_cansleep(pdata->gpio_hp_mute,
388                                 !SND_SOC_DAPM_EVENT_ON(event));
389
390         return 0;
391 }
392
393 static int tegra_rt5640_event_int_mic(struct snd_soc_dapm_widget *w,
394                                         struct snd_kcontrol *k, int event)
395 {
396         struct snd_soc_dapm_context *dapm = w->dapm;
397         struct snd_soc_card *card = dapm->card;
398         struct tegra_rt5640 *machine = snd_soc_card_get_drvdata(card);
399         struct tegra_rt5640_platform_data *pdata = machine->pdata;
400
401         if (machine->dmic_reg) {
402                 if (SND_SOC_DAPM_EVENT_ON(event))
403                         regulator_enable(machine->dmic_reg);
404                 else
405                         regulator_disable(machine->dmic_reg);
406         }
407
408         if (!(machine->gpio_requested & GPIO_INT_MIC_EN))
409                 return 0;
410
411         gpio_set_value_cansleep(pdata->gpio_int_mic_en,
412                                 SND_SOC_DAPM_EVENT_ON(event));
413
414         return 0;
415 }
416
417 static int tegra_rt5640_event_ext_mic(struct snd_soc_dapm_widget *w,
418                                         struct snd_kcontrol *k, int event)
419 {
420         struct snd_soc_dapm_context *dapm = w->dapm;
421         struct snd_soc_card *card = dapm->card;
422         struct tegra_rt5640 *machine = snd_soc_card_get_drvdata(card);
423         struct tegra_rt5640_platform_data *pdata = machine->pdata;
424
425         if (!(machine->gpio_requested & GPIO_EXT_MIC_EN))
426                 return 0;
427
428         gpio_set_value_cansleep(pdata->gpio_ext_mic_en,
429                                 !SND_SOC_DAPM_EVENT_ON(event));
430
431         return 0;
432 }
433
434 static const struct snd_soc_dapm_widget cardhu_dapm_widgets[] = {
435         SND_SOC_DAPM_SPK("Int Spk", tegra_rt5640_event_int_spk),
436         SND_SOC_DAPM_HP("Headphone Jack", tegra_rt5640_event_hp),
437         SND_SOC_DAPM_MIC("Mic Jack", tegra_rt5640_event_ext_mic),
438         SND_SOC_DAPM_MIC("Int Mic", tegra_rt5640_event_int_mic),
439 };
440
441 static const struct snd_soc_dapm_route cardhu_audio_map[] = {
442         {"Headphone Jack", NULL, "HPOR"},
443         {"Headphone Jack", NULL, "HPOL"},
444         {"Int Spk", NULL, "SPORP"},
445         {"Int Spk", NULL, "SPORN"},
446         {"Int Spk", NULL, "SPOLP"},
447         {"Int Spk", NULL, "SPOLN"},
448         {"micbias1", NULL, "Mic Jack"},
449         {"IN1P", NULL, "micbias1"},
450         {"IN1N", NULL, "micbias1"},
451         {"micbias1", NULL, "Int Mic"},
452         {"IN2P", NULL, "micbias1"},
453 };
454
455 static const struct snd_kcontrol_new cardhu_controls[] = {
456         SOC_DAPM_PIN_SWITCH("Int Spk"),
457         SOC_DAPM_PIN_SWITCH("Headphone Jack"),
458         SOC_DAPM_PIN_SWITCH("Mic Jack"),
459         SOC_DAPM_PIN_SWITCH("Int Mic"),
460 };
461
462 static int tegra_rt5640_init(struct snd_soc_pcm_runtime *rtd)
463 {
464         struct snd_soc_codec *codec = rtd->codec;
465         struct snd_soc_dapm_context *dapm = &codec->dapm;
466         struct snd_soc_card *card = codec->card;
467         struct tegra_rt5640 *machine = snd_soc_card_get_drvdata(card);
468         struct tegra_rt5640_platform_data *pdata = machine->pdata;
469         int ret;
470
471         if (gpio_is_valid(pdata->gpio_spkr_en)) {
472                 ret = gpio_request(pdata->gpio_spkr_en, "spkr_en");
473                 if (ret) {
474                         dev_err(card->dev, "cannot get spkr_en gpio\n");
475                         return ret;
476                 }
477                 machine->gpio_requested |= GPIO_SPKR_EN;
478
479                 gpio_direction_output(pdata->gpio_spkr_en, 0);
480         }
481
482         if (gpio_is_valid(pdata->gpio_hp_mute)) {
483                 ret = gpio_request(pdata->gpio_hp_mute, "hp_mute");
484                 if (ret) {
485                         dev_err(card->dev, "cannot get hp_mute gpio\n");
486                         return ret;
487                 }
488                 machine->gpio_requested |= GPIO_HP_MUTE;
489
490                 gpio_direction_output(pdata->gpio_hp_mute, 0);
491         }
492
493         if (gpio_is_valid(pdata->gpio_int_mic_en)) {
494                 ret = gpio_request(pdata->gpio_int_mic_en, "int_mic_en");
495                 if (ret) {
496                         dev_err(card->dev, "cannot get int_mic_en gpio\n");
497                         return ret;
498                 }
499                 machine->gpio_requested |= GPIO_INT_MIC_EN;
500
501                 /* Disable int mic; enable signal is active-high */
502                 gpio_direction_output(pdata->gpio_int_mic_en, 0);
503         }
504
505         if (gpio_is_valid(pdata->gpio_ext_mic_en)) {
506                 ret = gpio_request(pdata->gpio_ext_mic_en, "ext_mic_en");
507                 if (ret) {
508                         dev_err(card->dev, "cannot get ext_mic_en gpio\n");
509                         return ret;
510                 }
511                 machine->gpio_requested |= GPIO_EXT_MIC_EN;
512
513                 /* Disable ext mic; enable signal is active-low */
514                 gpio_direction_output(pdata->gpio_ext_mic_en, 1);
515         }
516
517         if (gpio_is_valid(pdata->gpio_hp_det)) {
518                 tegra_rt5640_hp_jack_gpio.gpio = pdata->gpio_hp_det;
519                 snd_soc_jack_new(codec, "Headphone Jack", SND_JACK_HEADPHONE,
520                                 &tegra_rt5640_hp_jack);
521 #ifndef CONFIG_SWITCH
522                 snd_soc_jack_add_pins(&tegra_rt5640_hp_jack,
523                                         ARRAY_SIZE(tegra_rt5640_hp_jack_pins),
524                                         tegra_rt5640_hp_jack_pins);
525 #else
526                 snd_soc_jack_notifier_register(&tegra_rt5640_hp_jack,
527                                         &tegra_rt5640_jack_detect_nb);
528 #endif
529                 snd_soc_jack_add_gpios(&tegra_rt5640_hp_jack,
530                                         1,
531                                         &tegra_rt5640_hp_jack_gpio);
532                 machine->gpio_requested |= GPIO_HP_DET;
533         }
534
535         ret = snd_soc_add_controls(codec, cardhu_controls,
536                         ARRAY_SIZE(cardhu_controls));
537         if (ret < 0)
538                 return ret;
539
540         snd_soc_dapm_new_controls(dapm, cardhu_dapm_widgets,
541                         ARRAY_SIZE(cardhu_dapm_widgets));
542
543         snd_soc_dapm_add_routes(dapm, cardhu_audio_map,
544                                 ARRAY_SIZE(cardhu_audio_map));
545         /* FIXME: Calculate automatically based on DAPM routes? */
546         snd_soc_dapm_nc_pin(dapm, "LOUTL");
547         snd_soc_dapm_nc_pin(dapm, "LOUTR");
548
549         snd_soc_dapm_sync(dapm);
550
551         return 0;
552 }
553
554 static struct snd_soc_dai_link tegra_rt5640_dai[] = {
555         {
556                 .name = "RT5640",
557                 .stream_name = "RT5640 PCM",
558                 .codec_name = "rt5640.4-001c",
559                 .platform_name = "tegra-pcm-audio",
560                 .cpu_dai_name = "tegra30-i2s.1",
561                 .codec_dai_name = "rt5640-aif1",
562                 .init = tegra_rt5640_init,
563                 .ops = &tegra_rt5640_ops,
564         },
565         {
566                 .name = "SPDIF",
567                 .stream_name = "SPDIF PCM",
568                 .codec_name = "spdif-dit.0",
569                 .platform_name = "tegra-pcm-audio",
570                 .cpu_dai_name = "tegra30-spdif",
571                 .codec_dai_name = "dit-hifi",
572                 .ops = &tegra_spdif_ops,
573         },
574         {
575                 .name = "BT-SCO",
576                 .stream_name = "BT SCO PCM",
577                 .codec_name = "spdif-dit.1",
578                 .platform_name = "tegra-pcm-audio",
579                 .cpu_dai_name = "tegra30-i2s.3",
580                 .codec_dai_name = "dit-hifi",
581                 .ops = &tegra_rt5640_bt_sco_ops,
582         },
583 };
584
585 static int tegra_rt5640_resume_pre(struct snd_soc_card *card)
586 {
587         int val;
588         struct snd_soc_jack_gpio *gpio = &tegra_rt5640_hp_jack_gpio;
589
590         if (gpio_is_valid(gpio->gpio)) {
591                 val = gpio_get_value(gpio->gpio);
592                 val = gpio->invert ? !val : val;
593                 snd_soc_jack_report(gpio->jack, val, gpio->report);
594         }
595
596         return 0;
597 }
598
599
600 static struct snd_soc_card snd_soc_tegra_rt5640 = {
601         .name = "tegra-rt5640",
602         .dai_link = tegra_rt5640_dai,
603         .num_links = ARRAY_SIZE(tegra_rt5640_dai),
604         .resume_pre = tegra_rt5640_resume_pre,
605 };
606
607 static __devinit int tegra_rt5640_driver_probe(struct platform_device *pdev)
608 {
609         struct snd_soc_card *card = &snd_soc_tegra_rt5640;
610         struct tegra_rt5640 *machine;
611         struct tegra_rt5640_platform_data *pdata;
612         int ret;
613
614         pdata = pdev->dev.platform_data;
615         if (!pdata) {
616                 dev_err(&pdev->dev, "No platform data supplied\n");
617                 return -EINVAL;
618         }
619
620         if (pdata->codec_name)
621                 card->dai_link->codec_name = pdata->codec_name;
622         if (pdata->codec_dai_name)
623                 card->dai_link->codec_dai_name = pdata->codec_dai_name;
624
625         machine = kzalloc(sizeof(struct tegra_rt5640), GFP_KERNEL);
626         if (!machine) {
627                 dev_err(&pdev->dev, "Can't allocate tegra_rt5640 struct\n");
628                 return -ENOMEM;
629         }
630
631         machine->pdata = pdata;
632
633         ret = tegra_asoc_utils_init(&machine->util_data, &pdev->dev, card);
634         if (ret)
635                 goto err_free_machine;
636
637         machine->cdc_en = regulator_get(NULL, "cdc_en");
638         if (WARN_ON(IS_ERR(machine->cdc_en))) {
639                 dev_err(&pdev->dev, "Couldn't get regulator cdc_en: %ld\n",
640                                                 PTR_ERR(machine->cdc_en));
641                 machine->cdc_en = 0;
642         } else {
643                 regulator_enable(machine->cdc_en);
644         }
645
646         machine->spk_reg = regulator_get(&pdev->dev, "vdd_spk_amp");
647         if (IS_ERR(machine->spk_reg)) {
648                 dev_info(&pdev->dev, "No speaker regulator found\n");
649                 machine->spk_reg = 0;
650         }
651
652 #ifdef CONFIG_SWITCH
653         /* Addd h2w swith class support */
654         ret = switch_dev_register(&tegra_rt5640_headset_switch);
655         if (ret < 0)
656                 goto err_fini_utils;
657 #endif
658
659         card->dev = &pdev->dev;
660         platform_set_drvdata(pdev, card);
661         snd_soc_card_set_drvdata(card, machine);
662
663         ret = snd_soc_register_card(card);
664         if (ret) {
665                 dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n",
666                         ret);
667                 goto err_unregister_switch;
668         }
669
670         if (!card->instantiated) {
671                 ret = -ENODEV;
672                 dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n",
673                         ret);
674                 goto err_unregister_card;
675         }
676
677         return 0;
678
679 err_unregister_card:
680         snd_soc_unregister_card(card);
681 err_unregister_switch:
682 #ifdef CONFIG_SWITCH
683         switch_dev_unregister(&tegra_rt5640_headset_switch);
684 err_fini_utils:
685 #endif
686         tegra_asoc_utils_fini(&machine->util_data);
687 err_free_machine:
688         kfree(machine);
689         return ret;
690 }
691
692 static int __devexit tegra_rt5640_driver_remove(struct platform_device *pdev)
693 {
694         struct snd_soc_card *card = platform_get_drvdata(pdev);
695         struct tegra_rt5640 *machine = snd_soc_card_get_drvdata(card);
696         struct tegra_rt5640_platform_data *pdata = machine->pdata;
697
698         if (machine->gpio_requested & GPIO_HP_DET)
699                 snd_soc_jack_free_gpios(&tegra_rt5640_hp_jack,
700                                         1,
701                                         &tegra_rt5640_hp_jack_gpio);
702         if (machine->gpio_requested & GPIO_EXT_MIC_EN)
703                 gpio_free(pdata->gpio_ext_mic_en);
704         if (machine->gpio_requested & GPIO_INT_MIC_EN)
705                 gpio_free(pdata->gpio_int_mic_en);
706         if (machine->gpio_requested & GPIO_HP_MUTE)
707                 gpio_free(pdata->gpio_hp_mute);
708         if (machine->gpio_requested & GPIO_SPKR_EN)
709                 gpio_free(pdata->gpio_spkr_en);
710         machine->gpio_requested = 0;
711
712         if (machine->spk_reg)
713                 regulator_put(machine->spk_reg);
714         if (machine->dmic_reg)
715                 regulator_put(machine->dmic_reg);
716
717         if (machine->cdc_en) {
718                 regulator_disable(machine->cdc_en);
719                 regulator_put(machine->cdc_en);
720         }
721
722         snd_soc_unregister_card(card);
723
724         tegra_asoc_utils_fini(&machine->util_data);
725
726 #ifdef CONFIG_SWITCH
727         switch_dev_unregister(&tegra_rt5640_headset_switch);
728 #endif
729         kfree(machine);
730
731         return 0;
732 }
733
734 static struct platform_driver tegra_rt5640_driver = {
735         .driver = {
736                 .name = DRV_NAME,
737                 .owner = THIS_MODULE,
738                 .pm = &snd_soc_pm_ops,
739         },
740         .probe = tegra_rt5640_driver_probe,
741         .remove = __devexit_p(tegra_rt5640_driver_remove),
742 };
743
744 static int __init tegra_rt5640_modinit(void)
745 {
746         return platform_driver_register(&tegra_rt5640_driver);
747 }
748 module_init(tegra_rt5640_modinit);
749
750 static void __exit tegra_rt5640_modexit(void)
751 {
752         platform_driver_unregister(&tegra_rt5640_driver);
753 }
754 module_exit(tegra_rt5640_modexit);
755
756 MODULE_AUTHOR("Johnny Qiu <joqiu@nvidia.com>");
757 MODULE_DESCRIPTION("Tegra+RT5640 machine ASoC driver");
758 MODULE_LICENSE("GPL");
759 MODULE_ALIAS("platform:" DRV_NAME);