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