2 * tegra_rt5640.c - Tegra machine ASoC driver for boards using ALC5640 codec.
4 * Author: Johnny Qiu <joqiu@nvidia.com>
5 * Copyright (C) 2011-2012, NVIDIA, Inc.
7 * Based on code copyright/by:
9 * Copyright 2007 Wolfson Microelectronics PLC.
10 * Author: Graeme Gregory
11 * graeme.gregory@wolfsonmicro.com or linux@wolfsonmicro.com
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.
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.
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
29 #include <asm/mach-types.h>
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>
37 #include <linux/switch.h>
40 #include <mach/tegra_rt5640_pdata.h>
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>
48 #include "../codecs/rt5639.h"
49 #include "../codecs/rt5640.h"
51 #include "tegra_pcm.h"
52 #include "tegra_asoc_utils.h"
54 #define DRV_NAME "tegra-snd-rt5640"
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)
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;
74 static int tegra_rt5640_hw_params(struct snd_pcm_substream *substream,
75 struct snd_pcm_hw_params *params)
77 struct snd_soc_pcm_runtime *rtd = substream->private_data;
78 struct snd_soc_dai *codec_dai = rtd->codec_dai;
79 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
80 struct snd_soc_codec *codec = rtd->codec;
81 struct snd_soc_card *card = codec->card;
82 struct tegra_rt5640 *machine = snd_soc_card_get_drvdata(card);
83 int srate, mclk, i2s_daifmt;
86 srate = params_rate(params);
88 err = tegra_asoc_utils_set_rate(&machine->util_data, srate, mclk);
90 if (!(machine->util_data.set_mclk % mclk)) {
91 mclk = machine->util_data.set_mclk;
93 dev_err(card->dev, "Can't configure clocks\n");
98 tegra_asoc_utils_lock_clk_rate(&machine->util_data, 1);
100 i2s_daifmt = SND_SOC_DAIFMT_NB_NF |
101 SND_SOC_DAIFMT_CBS_CFS;
103 i2s_daifmt |= SND_SOC_DAIFMT_I2S;
105 err = snd_soc_dai_set_fmt(codec_dai, i2s_daifmt);
107 dev_err(card->dev, "codec_dai fmt not set\n");
111 err = snd_soc_dai_set_fmt(cpu_dai, i2s_daifmt);
113 dev_err(card->dev, "cpu_dai fmt not set\n");
117 err = snd_soc_dai_set_sysclk(codec_dai, 0, mclk,
120 dev_err(card->dev, "codec_dai clock not set\n");
127 static int tegra_bt_sco_hw_params(struct snd_pcm_substream *substream,
128 struct snd_pcm_hw_params *params)
130 struct snd_soc_pcm_runtime *rtd = substream->private_data;
131 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
132 struct snd_soc_card *card = rtd->card;
133 struct tegra_rt5640 *machine = snd_soc_card_get_drvdata(card);
134 int srate, mclk, min_mclk;
137 srate = params_rate(params);
156 min_mclk = 64 * srate;
158 err = tegra_asoc_utils_set_rate(&machine->util_data, srate, mclk);
160 if (!(machine->util_data.set_mclk % min_mclk))
161 mclk = machine->util_data.set_mclk;
163 dev_err(card->dev, "Can't configure clocks\n");
168 tegra_asoc_utils_lock_clk_rate(&machine->util_data, 1);
170 err = snd_soc_dai_set_fmt(cpu_dai,
171 SND_SOC_DAIFMT_DSP_A |
172 SND_SOC_DAIFMT_NB_NF |
173 SND_SOC_DAIFMT_CBS_CFS);
175 dev_err(card->dev, "cpu_dai fmt not set\n");
182 static int tegra_spdif_hw_params(struct snd_pcm_substream *substream,
183 struct snd_pcm_hw_params *params)
185 struct snd_soc_pcm_runtime *rtd = substream->private_data;
186 struct snd_soc_card *card = rtd->card;
187 struct tegra_rt5640 *machine = snd_soc_card_get_drvdata(card);
188 int srate, mclk, min_mclk;
191 srate = params_rate(params);
210 min_mclk = 128 * srate;
212 err = tegra_asoc_utils_set_rate(&machine->util_data, srate, mclk);
214 if (!(machine->util_data.set_mclk % min_mclk))
215 mclk = machine->util_data.set_mclk;
217 dev_err(card->dev, "Can't configure clocks\n");
222 tegra_asoc_utils_lock_clk_rate(&machine->util_data, 1);
227 static int tegra_hw_free(struct snd_pcm_substream *substream)
229 struct snd_soc_pcm_runtime *rtd = substream->private_data;
230 struct tegra_rt5640 *machine = snd_soc_card_get_drvdata(rtd->card);
232 tegra_asoc_utils_lock_clk_rate(&machine->util_data, 0);
237 static struct snd_soc_ops tegra_rt5640_ops = {
238 .hw_params = tegra_rt5640_hw_params,
239 .hw_free = tegra_hw_free,
242 static struct snd_soc_ops tegra_rt5640_bt_sco_ops = {
243 .hw_params = tegra_bt_sco_hw_params,
244 .hw_free = tegra_hw_free,
247 static struct snd_soc_ops tegra_spdif_ops = {
248 .hw_params = tegra_spdif_hw_params,
249 .hw_free = tegra_hw_free,
252 static struct snd_soc_jack tegra_rt5640_hp_jack;
254 static struct snd_soc_jack_gpio tegra_rt5640_hp_jack_gpio = {
255 .name = "headphone detect",
256 .report = SND_JACK_HEADPHONE,
257 .debounce_time = 150,
262 /* These values are copied from Android WiredAccessoryObserver */
265 BIT_HEADSET = (1 << 0),
266 BIT_HEADSET_NO_MIC = (1 << 1),
269 static struct switch_dev tegra_rt5640_headset_switch = {
273 static int tegra_rt5640_jack_notifier(struct notifier_block *self,
274 unsigned long action, void *dev)
276 struct snd_soc_jack *jack = dev;
277 struct snd_soc_codec *codec = jack->codec;
278 struct snd_soc_card *card = codec->card;
279 struct tegra_rt5640 *machine = snd_soc_card_get_drvdata(card);
280 struct tegra_rt5640_platform_data *pdata = machine->pdata;
281 enum headset_state state = BIT_NO_HEADSET;
282 unsigned char status_jack = 0;
284 if (jack == &tegra_rt5640_hp_jack) {
286 /* Enable ext mic; enable signal is active-low */
287 gpio_direction_output(pdata->gpio_ext_mic_en, 0);
288 if (!strncmp(machine->pdata->codec_name, "rt5639", 6))
289 status_jack = rt5639_headset_detect(codec, 1);
290 else if (!strncmp(machine->pdata->codec_name, "rt5640",
292 status_jack = rt5640_headset_detect(codec, 1);
294 machine->jack_status &= ~SND_JACK_HEADPHONE;
295 machine->jack_status &= ~SND_JACK_MICROPHONE;
296 if (status_jack == RT5639_HEADPHO_DET ||
297 status_jack == RT5640_HEADPHO_DET)
298 machine->jack_status |=
300 else if (status_jack == RT5639_HEADSET_DET ||
301 status_jack == RT5640_HEADSET_DET) {
302 machine->jack_status |=
304 machine->jack_status |=
308 /* Disable ext mic; enable signal is active-low */
309 gpio_direction_output(pdata->gpio_ext_mic_en, 1);
310 if (!strncmp(machine->pdata->codec_name, "rt5639", 6))
311 rt5639_headset_detect(codec, 0);
312 else if (!strncmp(machine->pdata->codec_name, "rt5640",
314 rt5640_headset_detect(codec, 0);
316 machine->jack_status &= ~SND_JACK_HEADPHONE;
317 machine->jack_status &= ~SND_JACK_MICROPHONE;
321 switch (machine->jack_status) {
322 case SND_JACK_HEADPHONE:
323 state = BIT_HEADSET_NO_MIC;
325 case SND_JACK_HEADSET:
328 case SND_JACK_MICROPHONE:
329 /* mic: would not report */
331 state = BIT_NO_HEADSET;
334 switch_set_state(&tegra_rt5640_headset_switch, state);
339 static struct notifier_block tegra_rt5640_jack_detect_nb = {
340 .notifier_call = tegra_rt5640_jack_notifier,
343 static struct snd_soc_jack_pin tegra_rt5640_hp_jack_pins[] = {
345 .pin = "Headphone Jack",
346 .mask = SND_JACK_HEADPHONE,
352 static int tegra_rt5640_event_int_spk(struct snd_soc_dapm_widget *w,
353 struct snd_kcontrol *k, int event)
355 struct snd_soc_dapm_context *dapm = w->dapm;
356 struct snd_soc_card *card = dapm->card;
357 struct tegra_rt5640 *machine = snd_soc_card_get_drvdata(card);
358 struct tegra_rt5640_platform_data *pdata = machine->pdata;
360 if (machine->spk_reg) {
361 if (SND_SOC_DAPM_EVENT_ON(event))
362 regulator_enable(machine->spk_reg);
364 regulator_disable(machine->spk_reg);
367 if (!(machine->gpio_requested & GPIO_SPKR_EN))
370 gpio_set_value_cansleep(pdata->gpio_spkr_en,
371 SND_SOC_DAPM_EVENT_ON(event));
376 static int tegra_rt5640_event_hp(struct snd_soc_dapm_widget *w,
377 struct snd_kcontrol *k, int event)
379 struct snd_soc_dapm_context *dapm = w->dapm;
380 struct snd_soc_card *card = dapm->card;
381 struct tegra_rt5640 *machine = snd_soc_card_get_drvdata(card);
382 struct tegra_rt5640_platform_data *pdata = machine->pdata;
384 if (!(machine->gpio_requested & GPIO_HP_MUTE))
387 gpio_set_value_cansleep(pdata->gpio_hp_mute,
388 !SND_SOC_DAPM_EVENT_ON(event));
393 static int tegra_rt5640_event_int_mic(struct snd_soc_dapm_widget *w,
394 struct snd_kcontrol *k, int event)
396 struct snd_soc_dapm_context *dapm = w->dapm;
397 struct snd_soc_card *card = dapm->card;
398 struct tegra_rt5640 *machine = snd_soc_card_get_drvdata(card);
399 struct tegra_rt5640_platform_data *pdata = machine->pdata;
401 if (machine->dmic_reg) {
402 if (SND_SOC_DAPM_EVENT_ON(event))
403 regulator_enable(machine->dmic_reg);
405 regulator_disable(machine->dmic_reg);
408 if (!(machine->gpio_requested & GPIO_INT_MIC_EN))
411 gpio_set_value_cansleep(pdata->gpio_int_mic_en,
412 SND_SOC_DAPM_EVENT_ON(event));
417 static int tegra_rt5640_event_ext_mic(struct snd_soc_dapm_widget *w,
418 struct snd_kcontrol *k, int event)
420 struct snd_soc_dapm_context *dapm = w->dapm;
421 struct snd_soc_card *card = dapm->card;
422 struct tegra_rt5640 *machine = snd_soc_card_get_drvdata(card);
423 struct tegra_rt5640_platform_data *pdata = machine->pdata;
425 if (!(machine->gpio_requested & GPIO_EXT_MIC_EN))
428 gpio_set_value_cansleep(pdata->gpio_ext_mic_en,
429 !SND_SOC_DAPM_EVENT_ON(event));
434 static const struct snd_soc_dapm_widget cardhu_dapm_widgets[] = {
435 SND_SOC_DAPM_SPK("Int Spk", tegra_rt5640_event_int_spk),
436 SND_SOC_DAPM_HP("Headphone Jack", tegra_rt5640_event_hp),
437 SND_SOC_DAPM_MIC("Mic Jack", tegra_rt5640_event_ext_mic),
438 SND_SOC_DAPM_MIC("Int Mic", tegra_rt5640_event_int_mic),
441 static const struct snd_soc_dapm_route cardhu_audio_map[] = {
442 {"Headphone Jack", NULL, "HPOR"},
443 {"Headphone Jack", NULL, "HPOL"},
444 {"Int Spk", NULL, "SPORP"},
445 {"Int Spk", NULL, "SPORN"},
446 {"Int Spk", NULL, "SPOLP"},
447 {"Int Spk", NULL, "SPOLN"},
448 {"micbias1", NULL, "Mic Jack"},
449 {"IN1P", NULL, "micbias1"},
450 {"IN1N", NULL, "micbias1"},
451 {"micbias1", NULL, "Int Mic"},
452 {"IN2P", NULL, "micbias1"},
455 static const struct snd_kcontrol_new cardhu_controls[] = {
456 SOC_DAPM_PIN_SWITCH("Int Spk"),
457 SOC_DAPM_PIN_SWITCH("Headphone Jack"),
458 SOC_DAPM_PIN_SWITCH("Mic Jack"),
459 SOC_DAPM_PIN_SWITCH("Int Mic"),
462 static int tegra_rt5640_init(struct snd_soc_pcm_runtime *rtd)
464 struct snd_soc_codec *codec = rtd->codec;
465 struct snd_soc_dapm_context *dapm = &codec->dapm;
466 struct snd_soc_card *card = codec->card;
467 struct tegra_rt5640 *machine = snd_soc_card_get_drvdata(card);
468 struct tegra_rt5640_platform_data *pdata = machine->pdata;
471 if (gpio_is_valid(pdata->gpio_spkr_en)) {
472 ret = gpio_request(pdata->gpio_spkr_en, "spkr_en");
474 dev_err(card->dev, "cannot get spkr_en gpio\n");
477 machine->gpio_requested |= GPIO_SPKR_EN;
479 gpio_direction_output(pdata->gpio_spkr_en, 0);
482 if (gpio_is_valid(pdata->gpio_hp_mute)) {
483 ret = gpio_request(pdata->gpio_hp_mute, "hp_mute");
485 dev_err(card->dev, "cannot get hp_mute gpio\n");
488 machine->gpio_requested |= GPIO_HP_MUTE;
490 gpio_direction_output(pdata->gpio_hp_mute, 0);
493 if (gpio_is_valid(pdata->gpio_int_mic_en)) {
494 ret = gpio_request(pdata->gpio_int_mic_en, "int_mic_en");
496 dev_err(card->dev, "cannot get int_mic_en gpio\n");
499 machine->gpio_requested |= GPIO_INT_MIC_EN;
501 /* Disable int mic; enable signal is active-high */
502 gpio_direction_output(pdata->gpio_int_mic_en, 0);
505 if (gpio_is_valid(pdata->gpio_ext_mic_en)) {
506 ret = gpio_request(pdata->gpio_ext_mic_en, "ext_mic_en");
508 dev_err(card->dev, "cannot get ext_mic_en gpio\n");
511 machine->gpio_requested |= GPIO_EXT_MIC_EN;
513 /* Disable ext mic; enable signal is active-low */
514 gpio_direction_output(pdata->gpio_ext_mic_en, 1);
517 if (gpio_is_valid(pdata->gpio_hp_det)) {
518 tegra_rt5640_hp_jack_gpio.gpio = pdata->gpio_hp_det;
519 snd_soc_jack_new(codec, "Headphone Jack", SND_JACK_HEADPHONE,
520 &tegra_rt5640_hp_jack);
521 #ifndef CONFIG_SWITCH
522 snd_soc_jack_add_pins(&tegra_rt5640_hp_jack,
523 ARRAY_SIZE(tegra_rt5640_hp_jack_pins),
524 tegra_rt5640_hp_jack_pins);
526 snd_soc_jack_notifier_register(&tegra_rt5640_hp_jack,
527 &tegra_rt5640_jack_detect_nb);
529 snd_soc_jack_add_gpios(&tegra_rt5640_hp_jack,
531 &tegra_rt5640_hp_jack_gpio);
532 machine->gpio_requested |= GPIO_HP_DET;
535 ret = snd_soc_add_controls(codec, cardhu_controls,
536 ARRAY_SIZE(cardhu_controls));
540 snd_soc_dapm_new_controls(dapm, cardhu_dapm_widgets,
541 ARRAY_SIZE(cardhu_dapm_widgets));
543 snd_soc_dapm_add_routes(dapm, cardhu_audio_map,
544 ARRAY_SIZE(cardhu_audio_map));
545 /* FIXME: Calculate automatically based on DAPM routes? */
546 snd_soc_dapm_nc_pin(dapm, "LOUTL");
547 snd_soc_dapm_nc_pin(dapm, "LOUTR");
549 snd_soc_dapm_sync(dapm);
554 static struct snd_soc_dai_link tegra_rt5640_dai[] = {
557 .stream_name = "RT5640 PCM",
558 .codec_name = "rt5640.4-001c",
559 .platform_name = "tegra-pcm-audio",
560 .cpu_dai_name = "tegra30-i2s.1",
561 .codec_dai_name = "rt5640-aif1",
562 .init = tegra_rt5640_init,
563 .ops = &tegra_rt5640_ops,
567 .stream_name = "SPDIF PCM",
568 .codec_name = "spdif-dit.0",
569 .platform_name = "tegra-pcm-audio",
570 .cpu_dai_name = "tegra30-spdif",
571 .codec_dai_name = "dit-hifi",
572 .ops = &tegra_spdif_ops,
576 .stream_name = "BT SCO PCM",
577 .codec_name = "spdif-dit.1",
578 .platform_name = "tegra-pcm-audio",
579 .cpu_dai_name = "tegra30-i2s.3",
580 .codec_dai_name = "dit-hifi",
581 .ops = &tegra_rt5640_bt_sco_ops,
585 static struct snd_soc_card snd_soc_tegra_rt5640 = {
586 .name = "tegra-rt5640",
587 .dai_link = tegra_rt5640_dai,
588 .num_links = ARRAY_SIZE(tegra_rt5640_dai),
591 static __devinit int tegra_rt5640_driver_probe(struct platform_device *pdev)
593 struct snd_soc_card *card = &snd_soc_tegra_rt5640;
594 struct tegra_rt5640 *machine;
595 struct tegra_rt5640_platform_data *pdata;
598 pdata = pdev->dev.platform_data;
600 dev_err(&pdev->dev, "No platform data supplied\n");
604 if (pdata->codec_name)
605 card->dai_link->codec_name = pdata->codec_name;
606 if (pdata->codec_dai_name)
607 card->dai_link->codec_dai_name = pdata->codec_dai_name;
609 machine = kzalloc(sizeof(struct tegra_rt5640), GFP_KERNEL);
611 dev_err(&pdev->dev, "Can't allocate tegra_rt5640 struct\n");
615 machine->pdata = pdata;
617 ret = tegra_asoc_utils_init(&machine->util_data, &pdev->dev, card);
619 goto err_free_machine;
621 machine->cdc_en = regulator_get(NULL, "cdc_en");
622 if (WARN_ON(IS_ERR(machine->cdc_en))) {
623 dev_err(&pdev->dev, "Couldn't get regulator cdc_en: %ld\n",
624 PTR_ERR(machine->cdc_en));
627 regulator_enable(machine->cdc_en);
630 machine->spk_reg = regulator_get(&pdev->dev, "vdd_spk_amp");
631 if (IS_ERR(machine->spk_reg)) {
632 dev_info(&pdev->dev, "No speaker regulator found\n");
633 machine->spk_reg = 0;
637 /* Addd h2w swith class support */
638 ret = switch_dev_register(&tegra_rt5640_headset_switch);
643 card->dev = &pdev->dev;
644 platform_set_drvdata(pdev, card);
645 snd_soc_card_set_drvdata(card, machine);
647 ret = snd_soc_register_card(card);
649 dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n",
651 goto err_unregister_switch;
654 if (!card->instantiated) {
656 dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n",
658 goto err_unregister_card;
664 snd_soc_unregister_card(card);
665 err_unregister_switch:
667 switch_dev_unregister(&tegra_rt5640_headset_switch);
670 tegra_asoc_utils_fini(&machine->util_data);
676 static int __devexit tegra_rt5640_driver_remove(struct platform_device *pdev)
678 struct snd_soc_card *card = platform_get_drvdata(pdev);
679 struct tegra_rt5640 *machine = snd_soc_card_get_drvdata(card);
680 struct tegra_rt5640_platform_data *pdata = machine->pdata;
682 if (machine->gpio_requested & GPIO_HP_DET)
683 snd_soc_jack_free_gpios(&tegra_rt5640_hp_jack,
685 &tegra_rt5640_hp_jack_gpio);
686 if (machine->gpio_requested & GPIO_EXT_MIC_EN)
687 gpio_free(pdata->gpio_ext_mic_en);
688 if (machine->gpio_requested & GPIO_INT_MIC_EN)
689 gpio_free(pdata->gpio_int_mic_en);
690 if (machine->gpio_requested & GPIO_HP_MUTE)
691 gpio_free(pdata->gpio_hp_mute);
692 if (machine->gpio_requested & GPIO_SPKR_EN)
693 gpio_free(pdata->gpio_spkr_en);
694 machine->gpio_requested = 0;
696 if (machine->spk_reg)
697 regulator_put(machine->spk_reg);
698 if (machine->dmic_reg)
699 regulator_put(machine->dmic_reg);
701 if (machine->cdc_en) {
702 regulator_disable(machine->cdc_en);
703 regulator_put(machine->cdc_en);
706 snd_soc_unregister_card(card);
708 tegra_asoc_utils_fini(&machine->util_data);
711 switch_dev_unregister(&tegra_rt5640_headset_switch);
718 static struct platform_driver tegra_rt5640_driver = {
721 .owner = THIS_MODULE,
722 .pm = &snd_soc_pm_ops,
724 .probe = tegra_rt5640_driver_probe,
725 .remove = __devexit_p(tegra_rt5640_driver_remove),
728 static int __init tegra_rt5640_modinit(void)
730 return platform_driver_register(&tegra_rt5640_driver);
732 module_init(tegra_rt5640_modinit);
734 static void __exit tegra_rt5640_modexit(void)
736 platform_driver_unregister(&tegra_rt5640_driver);
738 module_exit(tegra_rt5640_modexit);
740 MODULE_AUTHOR("Johnny Qiu <joqiu@nvidia.com>");
741 MODULE_DESCRIPTION("Tegra+RT5640 machine ASoC driver");
742 MODULE_LICENSE("GPL");
743 MODULE_ALIAS("platform:" DRV_NAME);