asoc: tegra: ALC5640 machine: Fix i2s for BT Sco
[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         enum headset_state state = BIT_NO_HEADSET;
281         unsigned char status_jack;
282
283         if (jack == &tegra_rt5640_hp_jack) {
284                 if (action) {
285                         if (!strncmp(machine->pdata->codec_name, "rt5639", 6))
286                                 status_jack = rt5639_headset_detect(codec, 1);
287                         else if (!strncmp(machine->pdata->codec_name, "rt5640",
288                                                                             6))
289                                 status_jack = rt5640_headset_detect(codec, 1);
290
291                         machine->jack_status &= ~SND_JACK_HEADPHONE;
292                         machine->jack_status &= ~SND_JACK_MICROPHONE;
293                         if (status_jack == RT5639_HEADPHO_DET ||
294                             status_jack == RT5640_HEADPHO_DET)
295                                         machine->jack_status |=
296                                                         SND_JACK_HEADPHONE;
297                         else if (status_jack == RT5639_HEADSET_DET ||
298                                  status_jack == RT5640_HEADSET_DET) {
299                                         machine->jack_status |=
300                                                         SND_JACK_HEADPHONE;
301                                         machine->jack_status |=
302                                                         SND_JACK_MICROPHONE;
303                         }
304                 } else {
305                         if (!strncmp(machine->pdata->codec_name, "rt5639", 6))
306                                 rt5639_headset_detect(codec, 0);
307                         else if (!strncmp(machine->pdata->codec_name, "rt5640",
308                                                                             6))
309                                 rt5640_headset_detect(codec, 0);
310
311                         machine->jack_status &= ~SND_JACK_HEADPHONE;
312                         machine->jack_status &= ~SND_JACK_MICROPHONE;
313                 }
314         }
315
316         switch (machine->jack_status) {
317         case SND_JACK_HEADPHONE:
318                 state = BIT_HEADSET_NO_MIC;
319                 break;
320         case SND_JACK_HEADSET:
321                 state = BIT_HEADSET;
322                 break;
323         case SND_JACK_MICROPHONE:
324                 /* mic: would not report */
325         default:
326                 state = BIT_NO_HEADSET;
327         }
328
329         switch_set_state(&tegra_rt5640_headset_switch, state);
330
331         return NOTIFY_OK;
332 }
333
334 static struct notifier_block tegra_rt5640_jack_detect_nb = {
335         .notifier_call = tegra_rt5640_jack_notifier,
336 };
337 #else
338 static struct snd_soc_jack_pin tegra_rt5640_hp_jack_pins[] = {
339         {
340                 .pin = "Headphone Jack",
341                 .mask = SND_JACK_HEADPHONE,
342         },
343 };
344
345 #endif
346
347 static int tegra_rt5640_event_int_spk(struct snd_soc_dapm_widget *w,
348                                         struct snd_kcontrol *k, int event)
349 {
350         struct snd_soc_dapm_context *dapm = w->dapm;
351         struct snd_soc_card *card = dapm->card;
352         struct tegra_rt5640 *machine = snd_soc_card_get_drvdata(card);
353         struct tegra_rt5640_platform_data *pdata = machine->pdata;
354
355         if (machine->spk_reg) {
356                 if (SND_SOC_DAPM_EVENT_ON(event))
357                         regulator_enable(machine->spk_reg);
358                 else
359                         regulator_disable(machine->spk_reg);
360         }
361
362         if (!(machine->gpio_requested & GPIO_SPKR_EN))
363                 return 0;
364
365         gpio_set_value_cansleep(pdata->gpio_spkr_en,
366                                 SND_SOC_DAPM_EVENT_ON(event));
367
368         return 0;
369 }
370
371 static int tegra_rt5640_event_hp(struct snd_soc_dapm_widget *w,
372                                         struct snd_kcontrol *k, int event)
373 {
374         struct snd_soc_dapm_context *dapm = w->dapm;
375         struct snd_soc_card *card = dapm->card;
376         struct tegra_rt5640 *machine = snd_soc_card_get_drvdata(card);
377         struct tegra_rt5640_platform_data *pdata = machine->pdata;
378
379         if (!(machine->gpio_requested & GPIO_HP_MUTE))
380                 return 0;
381
382         gpio_set_value_cansleep(pdata->gpio_hp_mute,
383                                 !SND_SOC_DAPM_EVENT_ON(event));
384
385         return 0;
386 }
387
388 static int tegra_rt5640_event_int_mic(struct snd_soc_dapm_widget *w,
389                                         struct snd_kcontrol *k, int event)
390 {
391         struct snd_soc_dapm_context *dapm = w->dapm;
392         struct snd_soc_card *card = dapm->card;
393         struct tegra_rt5640 *machine = snd_soc_card_get_drvdata(card);
394         struct tegra_rt5640_platform_data *pdata = machine->pdata;
395
396         if (machine->dmic_reg) {
397                 if (SND_SOC_DAPM_EVENT_ON(event))
398                         regulator_enable(machine->dmic_reg);
399                 else
400                         regulator_disable(machine->dmic_reg);
401         }
402
403         if (!(machine->gpio_requested & GPIO_INT_MIC_EN))
404                 return 0;
405
406         gpio_set_value_cansleep(pdata->gpio_int_mic_en,
407                                 SND_SOC_DAPM_EVENT_ON(event));
408
409         return 0;
410 }
411
412 static int tegra_rt5640_event_ext_mic(struct snd_soc_dapm_widget *w,
413                                         struct snd_kcontrol *k, int event)
414 {
415         struct snd_soc_dapm_context *dapm = w->dapm;
416         struct snd_soc_card *card = dapm->card;
417         struct tegra_rt5640 *machine = snd_soc_card_get_drvdata(card);
418         struct tegra_rt5640_platform_data *pdata = machine->pdata;
419
420         if (!(machine->gpio_requested & GPIO_EXT_MIC_EN))
421                 return 0;
422
423         gpio_set_value_cansleep(pdata->gpio_ext_mic_en,
424                                 !SND_SOC_DAPM_EVENT_ON(event));
425
426         return 0;
427 }
428
429 static const struct snd_soc_dapm_widget cardhu_dapm_widgets[] = {
430         SND_SOC_DAPM_SPK("Int Spk", tegra_rt5640_event_int_spk),
431         SND_SOC_DAPM_HP("Headphone Jack", tegra_rt5640_event_hp),
432         SND_SOC_DAPM_MIC("Mic Jack", tegra_rt5640_event_ext_mic),
433         SND_SOC_DAPM_MIC("Int Mic", tegra_rt5640_event_int_mic),
434 };
435
436 static const struct snd_soc_dapm_route cardhu_audio_map[] = {
437         {"Headphone Jack", NULL, "HPOR"},
438         {"Headphone Jack", NULL, "HPOL"},
439         {"Int Spk", NULL, "SPORP"},
440         {"Int Spk", NULL, "SPORN"},
441         {"Int Spk", NULL, "SPOLP"},
442         {"Int Spk", NULL, "SPOLN"},
443         {"micbias1", NULL, "Mic Jack"},
444         {"IN1P", NULL, "micbias1"},
445         {"IN1N", NULL, "micbias1"},
446         {"micbias1", NULL, "Int Mic"},
447         {"IN2P", NULL, "micbias1"},
448 };
449
450 static const struct snd_kcontrol_new cardhu_controls[] = {
451         SOC_DAPM_PIN_SWITCH("Int Spk"),
452         SOC_DAPM_PIN_SWITCH("Headphone Jack"),
453         SOC_DAPM_PIN_SWITCH("Mic Jack"),
454         SOC_DAPM_PIN_SWITCH("Int Mic"),
455 };
456
457 static int tegra_rt5640_init(struct snd_soc_pcm_runtime *rtd)
458 {
459         struct snd_soc_codec *codec = rtd->codec;
460         struct snd_soc_dapm_context *dapm = &codec->dapm;
461         struct snd_soc_card *card = codec->card;
462         struct tegra_rt5640 *machine = snd_soc_card_get_drvdata(card);
463         struct tegra_rt5640_platform_data *pdata = machine->pdata;
464         int ret;
465
466         if (gpio_is_valid(pdata->gpio_spkr_en)) {
467                 ret = gpio_request(pdata->gpio_spkr_en, "spkr_en");
468                 if (ret) {
469                         dev_err(card->dev, "cannot get spkr_en gpio\n");
470                         return ret;
471                 }
472                 machine->gpio_requested |= GPIO_SPKR_EN;
473
474                 gpio_direction_output(pdata->gpio_spkr_en, 0);
475         }
476
477         if (gpio_is_valid(pdata->gpio_hp_mute)) {
478                 ret = gpio_request(pdata->gpio_hp_mute, "hp_mute");
479                 if (ret) {
480                         dev_err(card->dev, "cannot get hp_mute gpio\n");
481                         return ret;
482                 }
483                 machine->gpio_requested |= GPIO_HP_MUTE;
484
485                 gpio_direction_output(pdata->gpio_hp_mute, 0);
486         }
487
488         if (gpio_is_valid(pdata->gpio_int_mic_en)) {
489                 ret = gpio_request(pdata->gpio_int_mic_en, "int_mic_en");
490                 if (ret) {
491                         dev_err(card->dev, "cannot get int_mic_en gpio\n");
492                         return ret;
493                 }
494                 machine->gpio_requested |= GPIO_INT_MIC_EN;
495
496                 /* Disable int mic; enable signal is active-high */
497                 gpio_direction_output(pdata->gpio_int_mic_en, 0);
498         }
499
500         if (gpio_is_valid(pdata->gpio_ext_mic_en)) {
501                 ret = gpio_request(pdata->gpio_ext_mic_en, "ext_mic_en");
502                 if (ret) {
503                         dev_err(card->dev, "cannot get ext_mic_en gpio\n");
504                         return ret;
505                 }
506                 machine->gpio_requested |= GPIO_EXT_MIC_EN;
507
508                 /* Enable ext mic; enable signal is active-low */
509                 gpio_direction_output(pdata->gpio_ext_mic_en, 0);
510         }
511
512         if (gpio_is_valid(pdata->gpio_hp_det)) {
513                 tegra_rt5640_hp_jack_gpio.gpio = pdata->gpio_hp_det;
514                 snd_soc_jack_new(codec, "Headphone Jack", SND_JACK_HEADPHONE,
515                                 &tegra_rt5640_hp_jack);
516 #ifndef CONFIG_SWITCH
517                 snd_soc_jack_add_pins(&tegra_rt5640_hp_jack,
518                                         ARRAY_SIZE(tegra_rt5640_hp_jack_pins),
519                                         tegra_rt5640_hp_jack_pins);
520 #else
521                 snd_soc_jack_notifier_register(&tegra_rt5640_hp_jack,
522                                         &tegra_rt5640_jack_detect_nb);
523 #endif
524                 snd_soc_jack_add_gpios(&tegra_rt5640_hp_jack,
525                                         1,
526                                         &tegra_rt5640_hp_jack_gpio);
527                 machine->gpio_requested |= GPIO_HP_DET;
528         }
529
530         ret = snd_soc_add_controls(codec, cardhu_controls,
531                         ARRAY_SIZE(cardhu_controls));
532         if (ret < 0)
533                 return ret;
534
535         snd_soc_dapm_new_controls(dapm, cardhu_dapm_widgets,
536                         ARRAY_SIZE(cardhu_dapm_widgets));
537
538         snd_soc_dapm_add_routes(dapm, cardhu_audio_map,
539                                 ARRAY_SIZE(cardhu_audio_map));
540         /* FIXME: Calculate automatically based on DAPM routes? */
541         snd_soc_dapm_nc_pin(dapm, "LOUTL");
542         snd_soc_dapm_nc_pin(dapm, "LOUTR");
543
544         snd_soc_dapm_sync(dapm);
545
546         return 0;
547 }
548
549 static struct snd_soc_dai_link tegra_rt5640_dai[] = {
550         {
551                 .name = "RT5640",
552                 .stream_name = "RT5640 PCM",
553                 .codec_name = "rt5640.4-001c",
554                 .platform_name = "tegra-pcm-audio",
555                 .cpu_dai_name = "tegra30-i2s.1",
556                 .codec_dai_name = "rt5640-aif1",
557                 .init = tegra_rt5640_init,
558                 .ops = &tegra_rt5640_ops,
559         },
560         {
561                 .name = "SPDIF",
562                 .stream_name = "SPDIF PCM",
563                 .codec_name = "spdif-dit.0",
564                 .platform_name = "tegra-pcm-audio",
565                 .cpu_dai_name = "tegra30-spdif",
566                 .codec_dai_name = "dit-hifi",
567                 .ops = &tegra_spdif_ops,
568         },
569         {
570                 .name = "BT-SCO",
571                 .stream_name = "BT SCO PCM",
572                 .codec_name = "spdif-dit.1",
573                 .platform_name = "tegra-pcm-audio",
574                 .cpu_dai_name = "tegra30-i2s.3",
575                 .codec_dai_name = "dit-hifi",
576                 .ops = &tegra_rt5640_bt_sco_ops,
577         },
578 };
579
580 static struct snd_soc_card snd_soc_tegra_rt5640 = {
581         .name = "tegra-rt5640",
582         .dai_link = tegra_rt5640_dai,
583         .num_links = ARRAY_SIZE(tegra_rt5640_dai),
584 };
585
586 static __devinit int tegra_rt5640_driver_probe(struct platform_device *pdev)
587 {
588         struct snd_soc_card *card = &snd_soc_tegra_rt5640;
589         struct tegra_rt5640 *machine;
590         struct tegra_rt5640_platform_data *pdata;
591         int ret;
592
593         pdata = pdev->dev.platform_data;
594         if (!pdata) {
595                 dev_err(&pdev->dev, "No platform data supplied\n");
596                 return -EINVAL;
597         }
598
599         if (pdata->codec_name)
600                 card->dai_link->codec_name = pdata->codec_name;
601         if (pdata->codec_dai_name)
602                 card->dai_link->codec_dai_name = pdata->codec_dai_name;
603
604         machine = kzalloc(sizeof(struct tegra_rt5640), GFP_KERNEL);
605         if (!machine) {
606                 dev_err(&pdev->dev, "Can't allocate tegra_rt5640 struct\n");
607                 return -ENOMEM;
608         }
609
610         machine->pdata = pdata;
611
612         ret = tegra_asoc_utils_init(&machine->util_data, &pdev->dev);
613         if (ret)
614                 goto err_free_machine;
615
616         machine->cdc_en = regulator_get(NULL, "cdc_en");
617         if (WARN_ON(IS_ERR(machine->cdc_en))) {
618                 dev_err(&pdev->dev, "Couldn't get regulator cdc_en: %ld\n",
619                                                 PTR_ERR(machine->cdc_en));
620                 machine->cdc_en = 0;
621         } else {
622                 regulator_enable(machine->cdc_en);
623         }
624
625         machine->spk_reg = regulator_get(&pdev->dev, "vdd_spk_amp");
626         if (IS_ERR(machine->spk_reg)) {
627                 dev_info(&pdev->dev, "No speaker regulator found\n");
628                 machine->spk_reg = 0;
629         }
630
631 #ifdef CONFIG_SWITCH
632         /* Addd h2w swith class support */
633         ret = switch_dev_register(&tegra_rt5640_headset_switch);
634         if (ret < 0)
635                 goto err_fini_utils;
636 #endif
637
638         card->dev = &pdev->dev;
639         platform_set_drvdata(pdev, card);
640         snd_soc_card_set_drvdata(card, machine);
641
642         ret = snd_soc_register_card(card);
643         if (ret) {
644                 dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n",
645                         ret);
646                 goto err_unregister_switch;
647         }
648
649         if (!card->instantiated) {
650                 ret = -ENODEV;
651                 dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n",
652                         ret);
653                 goto err_unregister_card;
654         }
655
656         return 0;
657
658 err_unregister_card:
659         snd_soc_unregister_card(card);
660 err_unregister_switch:
661 #ifdef CONFIG_SWITCH
662         switch_dev_unregister(&tegra_rt5640_headset_switch);
663 err_fini_utils:
664 #endif
665         tegra_asoc_utils_fini(&machine->util_data);
666 err_free_machine:
667         kfree(machine);
668         return ret;
669 }
670
671 static int __devexit tegra_rt5640_driver_remove(struct platform_device *pdev)
672 {
673         struct snd_soc_card *card = platform_get_drvdata(pdev);
674         struct tegra_rt5640 *machine = snd_soc_card_get_drvdata(card);
675         struct tegra_rt5640_platform_data *pdata = machine->pdata;
676
677         if (machine->gpio_requested & GPIO_HP_DET)
678                 snd_soc_jack_free_gpios(&tegra_rt5640_hp_jack,
679                                         1,
680                                         &tegra_rt5640_hp_jack_gpio);
681         if (machine->gpio_requested & GPIO_EXT_MIC_EN)
682                 gpio_free(pdata->gpio_ext_mic_en);
683         if (machine->gpio_requested & GPIO_INT_MIC_EN)
684                 gpio_free(pdata->gpio_int_mic_en);
685         if (machine->gpio_requested & GPIO_HP_MUTE)
686                 gpio_free(pdata->gpio_hp_mute);
687         if (machine->gpio_requested & GPIO_SPKR_EN)
688                 gpio_free(pdata->gpio_spkr_en);
689         machine->gpio_requested = 0;
690
691         if (machine->spk_reg)
692                 regulator_put(machine->spk_reg);
693         if (machine->dmic_reg)
694                 regulator_put(machine->dmic_reg);
695
696         if (machine->cdc_en) {
697                 regulator_disable(machine->cdc_en);
698                 regulator_put(machine->cdc_en);
699         }
700
701         snd_soc_unregister_card(card);
702
703         tegra_asoc_utils_fini(&machine->util_data);
704
705 #ifdef CONFIG_SWITCH
706         switch_dev_unregister(&tegra_rt5640_headset_switch);
707 #endif
708         kfree(machine);
709
710         return 0;
711 }
712
713 static struct platform_driver tegra_rt5640_driver = {
714         .driver = {
715                 .name = DRV_NAME,
716                 .owner = THIS_MODULE,
717                 .pm = &snd_soc_pm_ops,
718         },
719         .probe = tegra_rt5640_driver_probe,
720         .remove = __devexit_p(tegra_rt5640_driver_remove),
721 };
722
723 static int __init tegra_rt5640_modinit(void)
724 {
725         return platform_driver_register(&tegra_rt5640_driver);
726 }
727 module_init(tegra_rt5640_modinit);
728
729 static void __exit tegra_rt5640_modexit(void)
730 {
731         platform_driver_unregister(&tegra_rt5640_driver);
732 }
733 module_exit(tegra_rt5640_modexit);
734
735 MODULE_AUTHOR("Johnny Qiu <joqiu@nvidia.com>");
736 MODULE_DESCRIPTION("Tegra+RT5640 machine ASoC driver");
737 MODULE_LICENSE("GPL");
738 MODULE_ALIAS("platform:" DRV_NAME);