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