asoc: tegra: cs42l73: Add DMIC regulator on/off support
[linux-2.6.git] / sound / soc / tegra / tegra_cs42l73.c
1 /*
2  * tegra_cs42l73.c - Tegra machine ASoC driver for boards using CS42L73 codec.
3  *
4  * Author: Vijay Mali <vmali@nvidia.com>
5  * Copyright (C) 2011-2012, NVIDIA, Inc.
6  *
7  * Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved.
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License
10  * version 2 as published by the Free Software Foundation.
11  *
12  * This program is distributed in the hope that it will be useful, but
13  * WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
20  * 02110-1301 USA
21  *
22  */
23
24 #include <asm/mach-types.h>
25
26 #include <linux/clk.h>
27 #include <linux/module.h>
28 #include <linux/platform_device.h>
29 #include <linux/slab.h>
30 #include <linux/gpio.h>
31 #include <linux/regulator/consumer.h>
32 #include <linux/delay.h>
33 #ifdef CONFIG_SWITCH
34 #include <linux/switch.h>
35 #endif
36 #include <mach/tegra_asoc_pdata.h>
37 #include <mach/gpio-tegra.h>
38
39 #include <sound/core.h>
40 #include <sound/jack.h>
41 #include <sound/pcm.h>
42 #include <sound/pcm_params.h>
43 #include <sound/soc.h>
44
45 #include "../codecs/cs42l73.h"
46
47 #include "tegra_pcm.h"
48 #include "tegra_asoc_utils.h"
49
50 #define DRV_NAME "tegra-snd-cs42l73"
51
52 #define GPIO_SPKR_EN    BIT(0)
53 #define GPIO_HP_MUTE    BIT(1)
54 #define GPIO_INT_MIC_EN BIT(2)
55 #define GPIO_EXT_MIC_EN BIT(3)
56 #define GPIO_HP_DET     BIT(4)
57
58 struct tegra_cs42l73 {
59         struct tegra_asoc_utils_data util_data;
60         struct tegra_asoc_platform_data *pdata;
61         int gpio_requested;
62         bool init_done;
63         int is_call_mode;
64         int is_device_bt;
65         struct regulator *dmic_reg;
66         struct regulator *dmic_1v8_reg;
67         enum snd_soc_bias_level bias_level;
68         struct snd_soc_card *pcard;
69 #ifdef CONFIG_SWITCH
70         int jack_status;
71 #endif
72         int clock_enabled;
73 };
74
75 static int tegra_cs42l73_hw_params(struct snd_pcm_substream *substream,
76                                         struct snd_pcm_hw_params *params)
77 {
78         struct snd_soc_pcm_runtime *rtd = substream->private_data;
79         struct snd_soc_dai *codec_dai = rtd->codec_dai;
80         struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
81         struct snd_soc_codec *codec = rtd->codec;
82         struct snd_soc_card *card = codec->card;
83         struct tegra_cs42l73 *machine = snd_soc_card_get_drvdata(card);
84         struct tegra_asoc_platform_data *pdata = machine->pdata;
85         int srate, mclk, i2s_daifmt;
86         int err, rate;
87
88         srate = params_rate(params);
89
90         switch (srate) {
91         case 8000:
92                 mclk = 6144000;
93                 break;
94         case 16000:
95         case 32000:
96                 mclk = 12288000;
97                 break;
98         case 11025:
99                 mclk = 512 * srate;
100                 break;
101         default:
102                 mclk = 256 * srate;
103                 break;
104         }
105
106         i2s_daifmt = SND_SOC_DAIFMT_NB_NF;
107         i2s_daifmt |= pdata->i2s_param[HIFI_CODEC].is_i2s_master ?
108                         SND_SOC_DAIFMT_CBS_CFS : SND_SOC_DAIFMT_CBM_CFM;
109
110         switch (pdata->i2s_param[HIFI_CODEC].i2s_mode) {
111         case TEGRA_DAIFMT_I2S:
112                 i2s_daifmt |= SND_SOC_DAIFMT_I2S;
113                 break;
114         case TEGRA_DAIFMT_DSP_A:
115                 i2s_daifmt |= SND_SOC_DAIFMT_DSP_A;
116                 break;
117         case TEGRA_DAIFMT_DSP_B:
118                 i2s_daifmt |= SND_SOC_DAIFMT_DSP_B;
119                 break;
120         case TEGRA_DAIFMT_LEFT_J:
121                 i2s_daifmt |= SND_SOC_DAIFMT_LEFT_J;
122                 break;
123         case TEGRA_DAIFMT_RIGHT_J:
124                 i2s_daifmt |= SND_SOC_DAIFMT_RIGHT_J;
125                 break;
126         default:
127                 dev_err(card->dev, "Can't configure i2s format\n");
128                 return -EINVAL;
129         }
130
131         err = tegra_asoc_utils_set_rate(&machine->util_data, srate, mclk);
132         if (err < 0) {
133                 if (!(machine->util_data.set_mclk % mclk)) {
134                         mclk = machine->util_data.set_mclk;
135                 } else {
136                         dev_err(card->dev, "Can't configure clocks\n");
137                         return err;
138                 }
139         }
140
141         tegra_asoc_utils_lock_clk_rate(&machine->util_data, 1);
142
143         rate = clk_get_rate(machine->util_data.clk_cdev1);
144
145         err = snd_soc_dai_set_fmt(codec_dai, i2s_daifmt);
146         if (err < 0) {
147                 dev_err(card->dev, "codec_dai fmt not set\n");
148                 return err;
149         }
150
151         err = snd_soc_dai_set_fmt(cpu_dai, i2s_daifmt);
152         if (err < 0) {
153                 dev_err(card->dev, "cpu_dai fmt not set\n");
154                 return err;
155         }
156
157         err = snd_soc_dai_set_sysclk(codec_dai, 0, rate, SND_SOC_CLOCK_IN);
158         if (err < 0) {
159                 dev_err(card->dev, "codec_dai clock not set\n");
160                 return err;
161         }
162
163         return 0;
164 }
165
166 static int tegra_hw_free(struct snd_pcm_substream *substream)
167 {
168         struct snd_soc_pcm_runtime *rtd = substream->private_data;
169         struct tegra_cs42l73 *machine = snd_soc_card_get_drvdata(rtd->card);
170
171         tegra_asoc_utils_lock_clk_rate(&machine->util_data, 0);
172
173         return 0;
174 }
175
176 static struct snd_soc_ops tegra_cs42l73_ops = {
177         .hw_params = tegra_cs42l73_hw_params,
178         .hw_free = tegra_hw_free,
179 };
180
181
182 /* Headset jack */
183 struct snd_soc_jack tegra_cs42l73_hp_jack;
184
185
186 #ifdef CONFIG_SWITCH
187 /* These values are copied from Android WiredAccessoryObserver */
188 enum headset_state {
189         BIT_NO_HEADSET = 0,
190         BIT_HEADSET = (1 << 0),
191         BIT_HEADSET_NO_MIC = (1 << 1),
192 };
193
194 static struct switch_dev tegra_cs42l73_headset_switch = {
195         .name = "h2w",
196 };
197
198 /* Headset jack detection gpios */
199 static struct snd_soc_jack_gpio tegra_cs42l73_hp_jack_gpio = {
200         .name = "headphone detect",
201         .report = SND_JACK_HEADPHONE,
202         .debounce_time = 150,
203         .invert = 1,
204 };
205
206 static int tegra_cs42l73_jack_notifier(struct notifier_block *self,
207                               unsigned long action, void *dev)
208 {
209         struct snd_soc_jack *jack = dev;
210         struct snd_soc_codec *codec = jack->codec;
211         struct snd_soc_card *card = codec->card;
212         struct tegra_cs42l73 *machine = snd_soc_card_get_drvdata(card);
213         enum headset_state state = BIT_NO_HEADSET;
214
215         if (jack == &tegra_cs42l73_hp_jack) {
216                 machine->jack_status &= ~SND_JACK_HEADPHONE;
217                 machine->jack_status |= (action & SND_JACK_HEADPHONE);
218         } else {
219                 machine->jack_status &= ~SND_JACK_MICROPHONE;
220                 machine->jack_status |= (action & SND_JACK_MICROPHONE);
221         }
222
223         switch (machine->jack_status) {
224         case SND_JACK_HEADPHONE:
225                 state = BIT_HEADSET_NO_MIC;
226                 break;
227         case SND_JACK_HEADSET:
228                 state = BIT_HEADSET;
229                 break;
230         case SND_JACK_MICROPHONE:
231                 /* mic: would not report */
232         default:
233                 state = BIT_NO_HEADSET;
234         }
235
236         switch_set_state(&tegra_cs42l73_headset_switch, state);
237
238         return NOTIFY_OK;
239 }
240
241 static struct notifier_block tegra_cs42l73_jack_detect_nb = {
242         .notifier_call = tegra_cs42l73_jack_notifier,
243 };
244 #else
245 /* Headset jack detection DAPM pins */
246 static struct snd_soc_jack_pin tegra_cs42l73_hs_jack_pins[] = {
247         {
248                 .pin = "Headset Mic",
249                 .mask = SND_JACK_MICROPHONE,
250         },
251         {
252                 .pin = "Headphone",
253                 .mask = SND_JACK_HEADPHONE,
254         },
255 };
256 #endif
257
258 static int tegra_cs42l73_event_int_mic(struct snd_soc_dapm_widget *w,
259                                         struct snd_kcontrol *k, int event)
260 {
261         struct snd_soc_dapm_context *dapm = w->dapm;
262         struct snd_soc_card *card = dapm->card;
263         struct tegra_cs42l73 *machine = snd_soc_card_get_drvdata(card);
264         struct tegra_asoc_platform_data *pdata = machine->pdata;
265
266         if (machine->dmic_reg && machine->dmic_1v8_reg) {
267                 if (SND_SOC_DAPM_EVENT_ON(event)) {
268                         regulator_enable(machine->dmic_reg);
269                         regulator_enable(machine->dmic_1v8_reg);
270                 } else {
271                         regulator_disable(machine->dmic_reg);
272                         regulator_disable(machine->dmic_1v8_reg);
273                 }
274         }
275
276         if (!(machine->gpio_requested & GPIO_INT_MIC_EN))
277                 return 0;
278
279         gpio_set_value_cansleep(pdata->gpio_int_mic_en,
280                                 SND_SOC_DAPM_EVENT_ON(event));
281
282         return 0;
283 }
284
285 static int tegra_cs42l73_event_int_spk(struct snd_soc_dapm_widget *w,
286                                         struct snd_kcontrol *k, int event)
287 {
288         struct snd_soc_dapm_context *dapm = w->dapm;
289         struct snd_soc_card *card = dapm->card;
290         struct tegra_cs42l73 *machine = snd_soc_card_get_drvdata(card);
291         struct tegra_asoc_platform_data *pdata = machine->pdata;
292
293         if (!(machine->gpio_requested & GPIO_SPKR_EN))
294                 return 0;
295
296         gpio_set_value_cansleep(pdata->gpio_spkr_en,
297                                 SND_SOC_DAPM_EVENT_ON(event));
298         return 0;
299 }
300
301 /* CS42L73 widgets */
302 static const struct snd_soc_dapm_widget tegra_cs42l73_dapm_widgets[] = {
303         SND_SOC_DAPM_SPK("Int Spk", tegra_cs42l73_event_int_spk),
304         SND_SOC_DAPM_HP("Headphone", NULL),
305         SND_SOC_DAPM_MIC("Headset Mic", NULL),
306         SND_SOC_DAPM_MIC("Int D-Mic", tegra_cs42l73_event_int_mic),
307 };
308
309 /* cs42l73 Audio Map */
310 static const struct snd_soc_dapm_route tegra_cs42l73_audio_map[] = {
311         {"Int Spk", NULL, "SPKOUT"},
312         {"MIC2", NULL, "Headset Mic"},
313         /* Headphone (L+R)->  HPOUTA, HPOUTB */
314         {"Headphone", NULL, "HPOUTA"},
315         {"Headphone", NULL, "HPOUTB"},
316         /* DMIC -> DMIC Left/Right and VSPIN */
317         {"DMIC Left", NULL, "Int D-Mic"},
318         {"DMIC Right", NULL, "Int D-Mic"},
319         {"VSPIN", NULL, "Int D-Mic"},
320 };
321
322 static const struct snd_kcontrol_new tegra_cs42l73_controls[] = {
323         SOC_DAPM_PIN_SWITCH("Int Spk"),
324         SOC_DAPM_PIN_SWITCH("Int D-Mic"),
325 };
326
327 static int tegra_cs42l73_init(struct snd_soc_pcm_runtime *rtd)
328 {
329         struct snd_soc_codec *codec = rtd->codec;
330         struct snd_soc_dapm_context *dapm = &codec->dapm;
331         struct snd_soc_card *card = codec->card;
332         struct tegra_cs42l73 *machine = snd_soc_card_get_drvdata(card);
333         struct tegra_asoc_platform_data *pdata = machine->pdata;
334         int ret;
335
336
337         if (machine->init_done)
338                 return 0;
339
340         machine->init_done = true;
341
342 /*
343         machine->pcard = card;
344         machine->bias_level = SND_SOC_BIAS_STANDBY;
345         machine->clock_enabled = 1;
346 */
347
348         machine->bias_level = SND_SOC_BIAS_STANDBY;
349         machine->clock_enabled = 1;
350
351         ret = snd_soc_add_card_controls(card, tegra_cs42l73_controls,
352                         ARRAY_SIZE(tegra_cs42l73_controls));
353         if (ret < 0)
354                 return ret;
355
356         /* Add cs42l73 specific widgets */
357         ret = snd_soc_dapm_new_controls(dapm,
358                         tegra_cs42l73_dapm_widgets,
359                         ARRAY_SIZE(tegra_cs42l73_dapm_widgets));
360         if (ret)
361                 return ret;
362
363         /* Set up cs42l73 specific audio path audio_map */
364         snd_soc_dapm_add_routes(dapm,
365                 tegra_cs42l73_audio_map,
366                 ARRAY_SIZE(tegra_cs42l73_audio_map));
367
368                 snd_soc_dapm_sync(dapm);
369
370         if (gpio_is_valid(pdata->gpio_hp_det)) {
371                 /* Headphone detection */
372                 tegra_cs42l73_hp_jack_gpio.gpio = pdata->gpio_hp_det;
373                 snd_soc_jack_new(codec, "Headphone Jack",
374                                 SND_JACK_HEADSET, &tegra_cs42l73_hp_jack);
375
376 #ifndef CONFIG_SWITCH
377                 snd_soc_jack_add_pins(&tegra_cs42l73_hp_jack,
378                                 ARRAY_SIZE(tegra_cs42l73_hs_jack_pins),
379                                 tegra_cs42l73_hs_jack_pins);
380 #else
381                 snd_soc_jack_notifier_register(&tegra_cs42l73_hp_jack,
382                                         &tegra_cs42l73_jack_detect_nb);
383 #endif
384                 snd_soc_jack_add_gpios(&tegra_cs42l73_hp_jack,
385                                         1,
386                                         &tegra_cs42l73_hp_jack_gpio);
387                 /* FIX ME  Add Mic Jack notifier */
388                 machine->gpio_requested |= GPIO_HP_DET;
389         }
390
391         ret = tegra_asoc_utils_register_ctls(&machine->util_data);
392         if (ret < 0)
393                 return ret;
394
395         return 0;
396 }
397
398 static struct snd_soc_dai_link tegra_cs42l73_dai[] = {
399         {
400                 .name = "CS42L73",
401                 .stream_name = "VSP Playback Record",
402                 .codec_name = "cs42l73.0-004a",
403                 .platform_name = "tegra-pcm-audio",
404                 .cpu_dai_name = "tegra30-i2s.1",
405                 .codec_dai_name = "cs42l73-vsp",
406                 .init = tegra_cs42l73_init,
407                 .ops = &tegra_cs42l73_ops,
408         },
409 };
410
411 static int tegra_cs42l73_suspend_post(struct snd_soc_card *card)
412 {
413         struct snd_soc_jack_gpio *gpio = &tegra_cs42l73_hp_jack_gpio;
414
415         if (gpio_is_valid(gpio->gpio))
416                 disable_irq(gpio_to_irq(gpio->gpio));
417
418         return 0;
419 }
420
421 static int tegra_cs42l73_resume_pre(struct snd_soc_card *card)
422 {
423         int val;
424         struct snd_soc_jack_gpio *gpio = &tegra_cs42l73_hp_jack_gpio;
425
426         if (gpio_is_valid(gpio->gpio)) {
427                 val = gpio_get_value(gpio->gpio);
428                 val = gpio->invert ? !val : val;
429                 snd_soc_jack_report(gpio->jack, val, gpio->report);
430                 enable_irq(gpio_to_irq(gpio->gpio));
431         }
432
433         return 0;
434 }
435
436 static int tegra_cs42l73_set_bias_level(struct snd_soc_card *card,
437         struct snd_soc_dapm_context *dapm, enum snd_soc_bias_level level)
438 {
439         struct tegra_cs42l73 *machine = snd_soc_card_get_drvdata(card);
440
441         if (machine->bias_level == SND_SOC_BIAS_OFF &&
442                 level != SND_SOC_BIAS_OFF && (!machine->clock_enabled)) {
443                 machine->clock_enabled = 1;
444                 tegra_asoc_utils_clk_enable(&machine->util_data);
445                 machine->bias_level = level;
446         }
447
448         return 0;
449 }
450
451 static int tegra_cs42l73_set_bias_level_post(struct snd_soc_card *card,
452         struct snd_soc_dapm_context *dapm, enum snd_soc_bias_level level)
453 {
454         struct tegra_cs42l73 *machine = snd_soc_card_get_drvdata(card);
455
456         if (machine->bias_level != SND_SOC_BIAS_OFF &&
457                 level == SND_SOC_BIAS_OFF && machine->clock_enabled) {
458                 machine->clock_enabled = 0;
459                 tegra_asoc_utils_clk_disable(&machine->util_data);
460         }
461
462         machine->bias_level = level;
463
464         return 0 ;
465 }
466
467 static struct snd_soc_card snd_soc_tegra_cs42l73 = {
468         .name = "tegra-cs42l73",
469         .owner = THIS_MODULE,
470         .dai_link = tegra_cs42l73_dai,
471         .num_links = ARRAY_SIZE(tegra_cs42l73_dai),
472         .suspend_post = tegra_cs42l73_suspend_post,
473         .resume_pre = tegra_cs42l73_resume_pre,
474         .set_bias_level = tegra_cs42l73_set_bias_level,
475         .set_bias_level_post = tegra_cs42l73_set_bias_level_post,
476 };
477
478 static __devinit int tegra_cs42l73_driver_probe(struct platform_device *pdev)
479 {
480         struct snd_soc_card *card = &snd_soc_tegra_cs42l73;
481         struct tegra_cs42l73 *machine;
482         struct tegra_asoc_platform_data *pdata;
483         int ret;
484         pdata = pdev->dev.platform_data;
485         if (!pdata) {
486                 dev_err(&pdev->dev, "No platform data supplied\n");
487                 return -EINVAL;
488         }
489
490         if (pdata->codec_name)
491                 card->dai_link->codec_name = pdata->codec_name;
492
493         if (pdata->codec_dai_name)
494                 card->dai_link->codec_dai_name = pdata->codec_dai_name;
495
496         machine = kzalloc(sizeof(struct tegra_cs42l73), GFP_KERNEL);
497         if (!machine) {
498                 dev_err(&pdev->dev, "Can't allocate tegra_cs42l73 struct\n");
499                 return -ENOMEM;
500         }
501
502         if (gpio_is_valid(pdata->gpio_ldo1_en)) {
503                 ret = gpio_request(pdata->gpio_ldo1_en, "cs42l73");
504                 if (ret)
505                         dev_err(&pdev->dev, "Fail gpio_request AUDIO_LDO1\n");
506
507                 ret = gpio_direction_output(pdata->gpio_ldo1_en, 0);
508                 if (ret)
509                         dev_err(&pdev->dev, "Fail gpio_direction AUDIO_LDO1\n");
510
511                 msleep(200);
512         }
513
514         machine->pdata = pdata;
515
516         ret = tegra_asoc_utils_init(&machine->util_data, &pdev->dev, card);
517         if (ret)
518                 goto err_free_machine;
519
520         machine->dmic_reg = regulator_get(&pdev->dev, "vdd_mic");
521         if (IS_ERR(machine->dmic_reg)) {
522                 dev_info(&pdev->dev, "No digital mic regulator found\n");
523                 machine->dmic_reg = 0;
524         }
525
526         machine->dmic_1v8_reg = regulator_get(&pdev->dev, "vdd_1v8_mic");
527         if (IS_ERR(machine->dmic_1v8_reg)) {
528                 dev_info(&pdev->dev, "No digital mic regulator found\n");
529                 machine->dmic_1v8_reg = 0;
530         }
531
532 #ifdef CONFIG_SWITCH
533         /* Addd h2w swith class support */
534         ret = switch_dev_register(&tegra_cs42l73_headset_switch);
535         if (ret < 0)
536                 goto err_fini_utils;
537 #endif
538
539         card->dev = &pdev->dev;
540         platform_set_drvdata(pdev, card);
541         snd_soc_card_set_drvdata(card, machine);
542         card->dapm.idle_bias_off = 1;
543         ret = snd_soc_register_card(card);
544         if (ret) {
545                 dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n",
546                         ret);
547                 goto err_unregister_switch;
548         }
549
550         if (!card->instantiated) {
551                 ret = -ENODEV;
552                 dev_err(&pdev->dev, "sound card not instantiated (%d)\n",
553                         ret);
554                 goto err_unregister_card;
555         }
556
557         ret = tegra_asoc_utils_set_parent(&machine->util_data,
558                                 pdata->i2s_param[HIFI_CODEC].is_i2s_master);
559         if (ret) {
560                 dev_err(&pdev->dev, "tegra_asoc_utils_set_parent failed (%d)\n",
561                         ret);
562                 goto err_unregister_card;
563         }
564
565         return 0;
566
567 err_unregister_card:
568         snd_soc_unregister_card(card);
569 err_unregister_switch:
570 #ifdef CONFIG_SWITCH
571         switch_dev_unregister(&tegra_cs42l73_headset_switch);
572 err_fini_utils:
573 #endif
574         tegra_asoc_utils_fini(&machine->util_data);
575 err_free_machine:
576         kfree(machine);
577         return ret;
578
579 }
580
581 static int __devexit tegra_cs42l73_driver_remove(struct platform_device *pdev)
582 {
583         struct snd_soc_card *card = platform_get_drvdata(pdev);
584         struct tegra_cs42l73 *machine = snd_soc_card_get_drvdata(card);
585         struct tegra_asoc_platform_data *pdata = machine->pdata;
586
587         if (machine->gpio_requested & GPIO_HP_DET)
588                 snd_soc_jack_free_gpios(&tegra_cs42l73_hp_jack,
589                                         1,
590                                         &tegra_cs42l73_hp_jack_gpio);
591
592         machine->gpio_requested = 0;
593
594         if (machine->dmic_reg)
595                 regulator_put(machine->dmic_reg);
596         if (machine->dmic_1v8_reg)
597                 regulator_put(machine->dmic_1v8_reg);
598
599         if (gpio_is_valid(pdata->gpio_ldo1_en)) {
600                 gpio_set_value(pdata->gpio_ldo1_en, 0);
601                 gpio_free(pdata->gpio_ldo1_en);
602         }
603
604         snd_soc_unregister_card(card);
605
606         tegra_asoc_utils_fini(&machine->util_data);
607
608         kfree(machine);
609
610         return 0;
611 }
612
613 static struct platform_driver tegra_cs42l73_driver = {
614         .driver = {
615                 .name = DRV_NAME,
616                 .owner = THIS_MODULE,
617                 .pm = &snd_soc_pm_ops,
618         },
619         .probe = tegra_cs42l73_driver_probe,
620         .remove = __devexit_p(tegra_cs42l73_driver_remove),
621 };
622
623 static int __init tegra_cs42l73_modinit(void)
624 {
625         return platform_driver_register(&tegra_cs42l73_driver);
626 }
627 module_init(tegra_cs42l73_modinit);
628
629 static void __exit tegra_cs42l73_modexit(void)
630 {
631         platform_driver_unregister(&tegra_cs42l73_driver);
632 }
633 module_exit(tegra_cs42l73_modexit);
634
635 MODULE_AUTHOR("Vijay Mali <vmali@nvidia.com>");
636 MODULE_DESCRIPTION("Tegra+CS42L73 machine ASoC driver");
637 MODULE_LICENSE("GPL");
638 MODULE_ALIAS("platform:" DRV_NAME);