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