2 * tegra_machine_driver_mobile.c - Tegra ASoC Machine driver for mobile
4 * Copyright (c) 2017-2021 NVIDIA CORPORATION. All rights reserved.
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms and conditions of the GNU General Public License,
8 * version 2, as published by the Free Software Foundation.
10 * This program is distributed in the hope it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
19 #include <linux/module.h>
20 #include <linux/platform_device.h>
21 #include <linux/of_platform.h>
22 #include <linux/input.h>
23 #include <linux/gpio.h>
24 #include <linux/pm_runtime.h>
25 #include <sound/core.h>
26 #include <sound/jack.h>
27 #include <sound/pcm.h>
28 #include <sound/pcm_params.h>
29 #include <sound/soc.h>
30 #include <dt-bindings/sound/tas2552.h>
33 #include "tegra_asoc_machine_alt.h"
34 #include "tegra210_xbar_alt.h"
36 #define DRV_NAME "tegra-asoc:"
38 #define PARAMS(sformat, channels) \
43 .channels_min = channels, \
44 .channels_max = channels, \
48 static const struct tegra_machine_soc_data soc_data_tegra210 = {
49 .admaif_dai_link_start = TEGRA210_DAI_LINK_ADMAIF1,
50 .admaif_dai_link_end = TEGRA210_DAI_LINK_ADMAIF10,
51 #if IS_ENABLED(CONFIG_SND_SOC_TEGRA210_ADSP_ALT)
52 .adsp_pcm_dai_link_start = TEGRA210_DAI_LINK_ADSP_PCM1,
53 .adsp_pcm_dai_link_end = TEGRA210_DAI_LINK_ADSP_PCM2,
54 .adsp_compr_dai_link_start = TEGRA210_DAI_LINK_ADSP_COMPR1,
55 .adsp_compr_dai_link_end = TEGRA210_DAI_LINK_ADSP_COMPR2,
57 .sfc_dai_link = TEGRA210_DAI_LINK_SFC1_RX,
59 .write_idle_bias_off_state = false,
61 .ahub_links = tegra210_xbar_dai_links,
62 .num_ahub_links = TEGRA210_XBAR_DAI_LINKS,
63 .ahub_confs = tegra210_xbar_codec_conf,
64 .num_ahub_confs = TEGRA210_XBAR_CODEC_CONF,
68 static const struct tegra_machine_soc_data soc_data_tegra186 = {
69 .admaif_dai_link_start = TEGRA186_DAI_LINK_ADMAIF1,
70 .admaif_dai_link_end = TEGRA186_DAI_LINK_ADMAIF10,
71 #if IS_ENABLED(CONFIG_SND_SOC_TEGRA210_ADSP_ALT)
72 .adsp_pcm_dai_link_start = TEGRA186_DAI_LINK_ADSP_PCM1,
73 .adsp_pcm_dai_link_end = TEGRA186_DAI_LINK_ADSP_PCM2,
74 .adsp_compr_dai_link_start = TEGRA186_DAI_LINK_ADSP_COMPR1,
75 .adsp_compr_dai_link_end = TEGRA186_DAI_LINK_ADSP_COMPR2,
77 .sfc_dai_link = TEGRA186_DAI_LINK_SFC1_RX,
79 .write_idle_bias_off_state = true,
81 .ahub_links = tegra186_xbar_dai_links,
82 .num_ahub_links = TEGRA186_XBAR_DAI_LINKS,
83 .ahub_confs = tegra186_xbar_codec_conf,
84 .num_ahub_confs = TEGRA186_XBAR_CODEC_CONF,
87 static const char * const tegra_machine_srate_text[] = {
103 static const char * const tegra_machine_format_text[] = {
109 static const struct soc_enum tegra_machine_codec_rate =
110 SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(tegra_machine_srate_text),
111 tegra_machine_srate_text);
113 static const struct soc_enum tegra_machine_codec_format =
114 SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(tegra_machine_format_text),
115 tegra_machine_format_text);
117 static const int tegra_machine_srate_values[] = {
133 static const struct snd_soc_dapm_widget tegra_machine_dapm_widgets[] = {
134 SND_SOC_DAPM_SPK("x Int Spk", NULL),
135 SND_SOC_DAPM_HP("x Headphone Jack", NULL),
136 SND_SOC_DAPM_MIC("x Int Mic", NULL),
137 SND_SOC_DAPM_MIC("x Mic Jack", NULL),
139 SND_SOC_DAPM_SPK("d1 Headphone", NULL),
140 SND_SOC_DAPM_SPK("d2 Headphone", NULL),
141 SND_SOC_DAPM_SPK("d3 Headphone", NULL),
143 SND_SOC_DAPM_HP("w Headphone", NULL),
144 SND_SOC_DAPM_HP("x Headphone", NULL),
145 SND_SOC_DAPM_HP("y Headphone", NULL),
146 SND_SOC_DAPM_HP("z Headphone", NULL),
147 SND_SOC_DAPM_HP("l Headphone", NULL),
148 SND_SOC_DAPM_HP("m Headphone", NULL),
149 SND_SOC_DAPM_HP("n Headphone", NULL),
150 SND_SOC_DAPM_HP("o Headphone", NULL),
151 SND_SOC_DAPM_HP("s Headphone", NULL),
153 SND_SOC_DAPM_MIC("Int Mic", NULL),
154 SND_SOC_DAPM_MIC("w Mic", NULL),
155 SND_SOC_DAPM_MIC("x Mic", NULL),
156 SND_SOC_DAPM_MIC("y Mic", NULL),
157 SND_SOC_DAPM_MIC("z Mic", NULL),
158 SND_SOC_DAPM_MIC("l Mic", NULL),
159 SND_SOC_DAPM_MIC("m Mic", NULL),
160 SND_SOC_DAPM_MIC("n Mic", NULL),
161 SND_SOC_DAPM_MIC("o Mic", NULL),
162 SND_SOC_DAPM_MIC("a Mic", NULL),
163 SND_SOC_DAPM_MIC("b Mic", NULL),
164 SND_SOC_DAPM_MIC("c Mic", NULL),
165 SND_SOC_DAPM_MIC("d Mic", NULL),
166 SND_SOC_DAPM_MIC("s Mic", NULL),
168 SND_SOC_DAPM_LINE("x Line Out", NULL),
169 SND_SOC_DAPM_LINE("y Line Out", NULL),
170 SND_SOC_DAPM_LINE("x Line In", NULL),
171 SND_SOC_DAPM_LINE("y Line In", NULL),
174 static struct snd_soc_pcm_stream tegra_machine_asrc_link_params[] = {
175 PARAMS(SNDRV_PCM_FMTBIT_S32_LE, 8),
176 PARAMS(SNDRV_PCM_FMTBIT_S16_LE, 2),
177 PARAMS(SNDRV_PCM_FMTBIT_S16_LE, 2),
178 PARAMS(SNDRV_PCM_FMTBIT_S16_LE, 2),
179 PARAMS(SNDRV_PCM_FMTBIT_S16_LE, 2),
180 PARAMS(SNDRV_PCM_FMTBIT_S16_LE, 2),
183 static int tegra_machine_codec_get_rate(struct snd_kcontrol *kcontrol,
184 struct snd_ctl_elem_value *ucontrol)
186 struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
187 struct tegra_machine *machine = snd_soc_card_get_drvdata(card);
189 ucontrol->value.integer.value[0] = machine->rate_via_kcontrol;
194 static int tegra_machine_codec_put_rate(struct snd_kcontrol *kcontrol,
195 struct snd_ctl_elem_value *ucontrol)
197 struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
198 struct tegra_machine *machine = snd_soc_card_get_drvdata(card);
200 /* set the rate control flag */
201 machine->rate_via_kcontrol = ucontrol->value.integer.value[0];
206 static int tegra_machine_codec_get_format(struct snd_kcontrol *kcontrol,
207 struct snd_ctl_elem_value *ucontrol)
209 struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
210 struct tegra_machine *machine = snd_soc_card_get_drvdata(card);
212 ucontrol->value.integer.value[0] = machine->fmt_via_kcontrol;
217 static int tegra_machine_codec_put_format(struct snd_kcontrol *kcontrol,
218 struct snd_ctl_elem_value *ucontrol)
220 struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
221 struct tegra_machine *machine = snd_soc_card_get_drvdata(card);
223 /* set the format control flag */
224 machine->fmt_via_kcontrol = ucontrol->value.integer.value[0];
229 static int tegra_machine_set_params(struct snd_soc_card *card,
230 struct tegra_machine *machine,
232 unsigned int channels,
235 unsigned int mask = (1 << channels) - 1;
236 struct snd_soc_pcm_runtime *rtd;
237 int idx = 0, err = 0;
240 int num_of_dai_links = machine->soc_data->num_ahub_links +
241 machine->num_codec_links;
243 format_k = (machine->fmt_via_kcontrol == 2) ?
244 (1ULL << SNDRV_PCM_FORMAT_S32_LE) : formats;
246 /* update dai link hw_params */
247 list_for_each_entry(rtd, &card->rtd_list, list) {
248 if (rtd->dai_link->params) {
249 struct snd_soc_pcm_stream *dai_params;
252 (struct snd_soc_pcm_stream *)
253 rtd->dai_link->params;
255 dai_params->rate_min = rate;
256 dai_params->channels_min = channels;
257 dai_params->formats = format_k;
259 if ((idx >= machine->soc_data->num_ahub_links)
260 && (idx < num_of_dai_links)) {
263 /* TODO: why below overrite is needed */
264 dai_params->formats = formats;
266 fmt = rtd->dai_link->dai_fmt;
267 fmt &= SND_SOC_DAIFMT_FORMAT_MASK;
269 /* set TDM slot mask */
270 if (fmt == SND_SOC_DAIFMT_DSP_A ||
271 fmt == SND_SOC_DAIFMT_DSP_B) {
272 err = snd_soc_dai_set_tdm_slot(
277 "%s cpu DAI slot mask not set\n",
289 static int tegra_machine_dai_init(struct snd_soc_pcm_runtime *runtime,
290 unsigned int rate, unsigned int channels,
293 struct snd_soc_card *card = runtime->card;
294 struct tegra_machine *machine = snd_soc_card_get_drvdata(card);
295 struct snd_soc_pcm_stream *dai_params;
296 unsigned int aud_mclk, srate;
297 int err, sample_size;
298 struct snd_soc_pcm_runtime *rtd;
300 srate = (machine->rate_via_kcontrol) ?
301 tegra_machine_srate_values[machine->rate_via_kcontrol] :
305 case SNDRV_PCM_FORMAT_S8:
308 case SNDRV_PCM_FORMAT_S16_LE:
311 case SNDRV_PCM_FORMAT_S24_LE:
313 * I2S bit clock is derived from PLLA_OUT0 and size of
314 * 24 bits results in fractional value and the clock
315 * is not accurate with this. To have integer clock
316 * division below is used. It means there are additional
317 * bit clocks (8 cycles) which are ignored. Codec picks
318 * up data for other channel when LRCK signal toggles.
320 case SNDRV_PCM_FORMAT_S32_LE:
324 pr_err("Wrong format!\n");
327 formats = 1ULL << formats;
329 err = tegra_alt_asoc_utils_set_rate(&machine->audio_clock, srate,
330 channels, sample_size, 0, 0);
332 dev_err(card->dev, "Can't configure clocks\n");
336 aud_mclk = machine->audio_clock.set_aud_mclk_rate;
338 pr_debug("pll_a_out0 = %u Hz, aud_mclk = %u Hz, sample rate = %u Hz\n",
339 machine->audio_clock.set_pll_out_rate, aud_mclk, srate);
341 err = tegra_machine_set_params(card, machine, srate, channels, formats);
345 rtd = snd_soc_get_pcm_runtime(card, "rt565x-playback");
348 (struct snd_soc_pcm_stream *)rtd->dai_link->params;
350 dai_params->formats = (machine->fmt_via_kcontrol == 2) ?
351 (1ULL << SNDRV_PCM_FORMAT_S32_LE) : formats;
353 err = snd_soc_dai_set_sysclk(rtd->codec_dai, RT5659_SCLK_S_MCLK,
354 aud_mclk, SND_SOC_CLOCK_IN);
356 dev_err(card->dev, "codec_dai clock not set\n");
361 rtd = snd_soc_get_pcm_runtime(card, "rt565x-codec-sysclk-bclk1");
364 (struct snd_soc_pcm_stream *)rtd->dai_link->params;
366 dai_params->formats = (machine->fmt_via_kcontrol == 2) ?
367 (1ULL << SNDRV_PCM_FORMAT_S32_LE) : formats;
369 err = rt565x_manage_codec_sysclk(dai_params, rtd->codec_dai,
370 RT5659_PLL1_S_BCLK1);
372 dev_err(card->dev, "codec_dai clock not set\n");
378 rtd = snd_soc_get_pcm_runtime(card, "dspk-playback-r");
380 if (!strcmp(rtd->codec_dai->name, "tas2552-amplifier")) {
381 err = snd_soc_dai_set_sysclk(rtd->codec_dai,
382 TAS2552_PDM_CLK_IVCLKIN, aud_mclk,
385 dev_err(card->dev, "codec_dai clock not set\n");
391 rtd = snd_soc_get_pcm_runtime(card, "dspk-playback-l");
393 if (!strcmp(rtd->codec_dai->name, "tas2552-amplifier")) {
394 err = snd_soc_dai_set_sysclk(rtd->codec_dai,
395 TAS2552_PDM_CLK_IVCLKIN, aud_mclk,
398 dev_err(card->dev, "codec_dai clock not set\n");
407 static int tegra_machine_pcm_hw_params(struct snd_pcm_substream *substream,
408 struct snd_pcm_hw_params *params)
410 struct snd_soc_pcm_runtime *rtd = substream->private_data;
411 struct snd_soc_card *card = rtd->card;
414 err = tegra_machine_dai_init(rtd, params_rate(params),
415 params_channels(params),
416 params_format(params));
418 dev_err(card->dev, "Failed dai init\n");
425 static int tegra_machine_pcm_startup(struct snd_pcm_substream *substream)
427 struct snd_soc_pcm_runtime *rtd = substream->private_data;
428 struct tegra_machine *machine = snd_soc_card_get_drvdata(rtd->card);
430 tegra_alt_asoc_utils_clk_enable(&machine->audio_clock);
435 static void tegra_machine_pcm_shutdown(struct snd_pcm_substream *substream)
437 struct snd_soc_pcm_runtime *rtd = substream->private_data;
438 struct tegra_machine *machine = snd_soc_card_get_drvdata(rtd->card);
440 tegra_alt_asoc_utils_clk_disable(&machine->audio_clock);
443 static int tegra_machine_suspend_pre(struct snd_soc_card *card)
445 struct snd_soc_pcm_runtime *rtd;
447 /* DAPM dai link stream work for non pcm links */
448 list_for_each_entry(rtd, &card->rtd_list, list) {
449 if (rtd->dai_link->params)
450 INIT_DELAYED_WORK(&rtd->delayed_work, NULL);
456 #if IS_ENABLED(CONFIG_SND_SOC_TEGRA210_ADSP_ALT)
457 static int tegra_machine_compr_startup(struct snd_compr_stream *cstream)
459 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
460 struct snd_soc_card *card = rtd->card;
461 struct tegra_machine *machine = snd_soc_card_get_drvdata(card);
463 tegra_alt_asoc_utils_clk_enable(&machine->audio_clock);
468 static void tegra_machine_compr_shutdown(struct snd_compr_stream *cstream)
470 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
471 struct snd_soc_card *card = rtd->card;
472 struct tegra_machine *machine = snd_soc_card_get_drvdata(card);
474 tegra_alt_asoc_utils_clk_disable(&machine->audio_clock);
477 static int tegra_machine_compr_set_params(struct snd_compr_stream *cstream)
479 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
480 struct snd_soc_card *card = rtd->card;
481 struct snd_soc_platform *platform = rtd->platform;
482 struct snd_codec codec_params;
485 if (platform->driver->compr_ops &&
486 platform->driver->compr_ops->get_params) {
487 err = platform->driver->compr_ops->get_params(cstream,
490 dev_err(card->dev, "Failed to get compr params\n");
494 dev_err(card->dev, "compr ops not set\n");
498 err = tegra_machine_dai_init(rtd, codec_params.sample_rate,
500 SNDRV_PCM_FORMAT_S16_LE);
502 dev_err(card->dev, "Failed dai init\n");
510 static int tegra_machine_respeaker_init(struct snd_soc_pcm_runtime *rtd)
512 struct device *dev = rtd->card->dev;
515 /* ac108 codec driver hardcodes the freq as 24000000
516 * and source as PLL irrespective of args passed through
519 err = snd_soc_dai_set_sysclk(rtd->codec_dai, 0, 24000000,
522 dev_err(dev, "failed to set ac108 sysclk!\n");
529 static int tegra_machine_fepi_init(struct snd_soc_pcm_runtime *rtd)
531 struct device *dev = rtd->card->dev;
534 err = snd_soc_dai_set_sysclk(rtd->codec_dai, SGTL5000_SYSCLK, 12288000,
537 dev_err(dev, "failed to set sgtl5000 sysclk!\n");
544 static int tegra_machine_rt565x_init(struct snd_soc_pcm_runtime *rtd)
546 struct snd_soc_card *card = rtd->card;
547 struct snd_soc_jack *jack;
550 jack = devm_kzalloc(card->dev, sizeof(struct snd_soc_jack), GFP_KERNEL);
554 err = snd_soc_card_jack_new(card, "Headset Jack", SND_JACK_HEADSET,
557 dev_err(card->dev, "Headset Jack creation failed %d\n", err);
561 err = tegra_machine_add_codec_jack_control(card, rtd, jack);
563 dev_err(card->dev, "Failed to add jack control: %d\n", err);
567 err = rt5659_set_jack_detect(rtd->codec, jack);
569 dev_err(card->dev, "Failed to set jack for RT565x: %d\n", err);
573 /* single button supporting play/pause */
574 snd_jack_set_key(jack->jack, SND_JACK_BTN_0, KEY_MEDIA);
576 /* multiple buttons supporting play/pause and volume up/down */
577 snd_jack_set_key(jack->jack, SND_JACK_BTN_1, KEY_MEDIA);
578 snd_jack_set_key(jack->jack, SND_JACK_BTN_2, KEY_VOLUMEUP);
579 snd_jack_set_key(jack->jack, SND_JACK_BTN_3, KEY_VOLUMEDOWN);
581 snd_soc_dapm_sync(&card->dapm);
586 static int codec_init(struct tegra_machine *machine)
588 struct snd_soc_dai_link *dai_links = machine->asoc->dai_links;
589 unsigned int num_links = machine->asoc->num_links, i;
591 if (!dai_links || !num_links)
594 for (i = 0; i < num_links; i++) {
595 if (!dai_links[i].name)
598 if (strstr(dai_links[i].name, "rt565x-playback") ||
599 strstr(dai_links[i].name, "rt565x-codec-sysclk-bclk1"))
600 dai_links[i].init = tegra_machine_rt565x_init;
601 else if (strstr(dai_links[i].name, "fe-pi-audio-z-v2"))
602 dai_links[i].init = tegra_machine_fepi_init;
603 else if (strstr(dai_links[i].name, "respeaker-4-mic-array"))
604 dai_links[i].init = tegra_machine_respeaker_init;
610 static struct snd_soc_ops tegra_machine_pcm_ops = {
611 .hw_params = tegra_machine_pcm_hw_params,
612 .startup = tegra_machine_pcm_startup,
613 .shutdown = tegra_machine_pcm_shutdown,
616 #if IS_ENABLED(CONFIG_SND_SOC_TEGRA210_ADSP_ALT)
617 static struct snd_soc_compr_ops tegra_machine_compr_ops = {
618 .set_params = tegra_machine_compr_set_params,
619 .startup = tegra_machine_compr_startup,
620 .shutdown = tegra_machine_compr_shutdown,
624 static void set_dai_ops(struct tegra_machine *machine)
628 /* set ADMAIF dai_ops */
629 for (i = machine->soc_data->admaif_dai_link_start;
630 i <= machine->soc_data->admaif_dai_link_end; i++)
631 machine->asoc->dai_links[i].ops = &tegra_machine_pcm_ops;
632 #if IS_ENABLED(CONFIG_SND_SOC_TEGRA210_ADSP_ALT)
633 /* set ADSP PCM/COMPR */
634 for (i = machine->soc_data->adsp_pcm_dai_link_start;
635 i <= machine->soc_data->adsp_pcm_dai_link_end; i++)
636 machine->asoc->dai_links[i].ops = &tegra_machine_pcm_ops;
638 for (i = machine->soc_data->adsp_compr_dai_link_start;
639 i <= machine->soc_data->adsp_compr_dai_link_end; i++)
640 machine->asoc->dai_links[i].compr_ops =
641 &tegra_machine_compr_ops;
643 #if IS_ENABLED(CONFIG_SND_SOC_TEGRA186_ASRC_ALT)
644 if (!(of_machine_is_compatible("nvidia,tegra210") ||
645 of_machine_is_compatible("nvidia,tegra210b01"))) {
646 /* set ASRC params. The default is 2 channels */
647 for (i = 0; i < 6; i++) {
648 int tx = TEGRA186_DAI_LINK_ASRC1_TX1 + i;
649 int rx = TEGRA186_DAI_LINK_ASRC1_RX1 + i;
651 machine->asoc->dai_links[tx].params =
652 &tegra_machine_asrc_link_params[i];
653 machine->asoc->dai_links[rx].params =
654 &tegra_machine_asrc_link_params[i];
660 static int add_dai_links(struct platform_device *pdev)
662 struct snd_soc_card *card = platform_get_drvdata(pdev);
663 struct tegra_machine *machine = snd_soc_card_get_drvdata(card);
666 machine->asoc = devm_kzalloc(&pdev->dev, sizeof(*machine->asoc),
671 ret = tegra_asoc_populate_dai_links(pdev);
675 ret = tegra_asoc_populate_codec_confs(pdev);
679 ret = codec_init(machine);
683 set_dai_ops(machine);
688 static const struct snd_kcontrol_new tegra_machine_controls[] = {
689 SOC_ENUM_EXT("codec-x rate", tegra_machine_codec_rate,
690 tegra_machine_codec_get_rate, tegra_machine_codec_put_rate),
691 SOC_ENUM_EXT("codec-x format", tegra_machine_codec_format,
692 tegra_machine_codec_get_format, tegra_machine_codec_put_format),
695 static struct snd_soc_card snd_soc_tegra_card = {
696 .owner = THIS_MODULE,
697 .controls = tegra_machine_controls,
698 .num_controls = ARRAY_SIZE(tegra_machine_controls),
699 .dapm_widgets = tegra_machine_dapm_widgets,
700 .num_dapm_widgets = ARRAY_SIZE(tegra_machine_dapm_widgets),
701 .suspend_pre = tegra_machine_suspend_pre,
702 .fully_routed = true,
705 /* structure to match device tree node */
706 static const struct of_device_id tegra_machine_of_match[] = {
707 { .compatible = "nvidia,tegra-audio-t186ref-mobile-rt565x",
708 .data = &soc_data_tegra186 },
709 { .compatible = "nvidia,tegra-audio-t210ref-mobile-rt565x",
710 .data = &soc_data_tegra210 },
711 { .compatible = "nvidia,tegra-audio-mystique",
712 .data = &soc_data_tegra186 },
716 static int tegra_machine_driver_probe(struct platform_device *pdev)
718 struct device_node *np = pdev->dev.of_node;
719 struct snd_soc_card *card = &snd_soc_tegra_card;
720 struct tegra_machine *machine;
722 const struct of_device_id *match;
724 card->dev = &pdev->dev;
725 /* parse card name first to log errors with proper device name */
726 ret = snd_soc_of_parse_card_name(card, "nvidia,model");
730 match = of_match_device(tegra_machine_of_match, &pdev->dev);
732 dev_err(&pdev->dev, "Error: No device match found\n");
737 dev_err(&pdev->dev, "No DT node for tegra machine driver");
741 machine = devm_kzalloc(&pdev->dev, sizeof(*machine), GFP_KERNEL);
745 machine->soc_data = (struct tegra_machine_soc_data *)match->data;
746 if (!machine->soc_data)
749 platform_set_drvdata(pdev, card);
750 snd_soc_card_set_drvdata(card, machine);
752 if (machine->soc_data->write_cdev1_state)
753 machine->audio_clock.clk_cdev1_state = 0;
755 if (machine->soc_data->write_idle_bias_off_state)
756 card->dapm.idle_bias_off = true;
758 ret = snd_soc_of_parse_audio_routing(card,
759 "nvidia,audio-routing");
763 memset(&machine->audio_clock, 0, sizeof(machine->audio_clock));
764 if (of_property_read_u32(np, "mclk-fs",
765 &machine->audio_clock.mclk_scale) < 0)
766 dev_dbg(&pdev->dev, "Missing property mclk-fs\n");
768 if (of_property_read_bool(np, "fixed-pll")) {
769 machine->audio_clock.fixed_pll = true;
770 dev_info(&pdev->dev, "PLL configuration is fixed from DT\n");
773 tegra_machine_dma_set_mask(pdev);
775 ret = add_dai_links(pdev);
779 ret = tegra_alt_asoc_utils_init(&machine->audio_clock,
785 ret = snd_soc_register_card(card);
787 dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n",
792 tegra_machine_add_i2s_codec_controls(card,
793 machine->soc_data->num_ahub_links +
794 machine->num_codec_links);
798 release_asoc_phandles(machine);
802 static int tegra_machine_driver_remove(struct platform_device *pdev)
804 struct snd_soc_card *card = platform_get_drvdata(pdev);
806 snd_soc_unregister_card(card);
812 static void tegra_asoc_machine_resume(struct device *dev)
814 WARN_ON(snd_soc_resume(dev));
817 #define tegra_asoc_machine_resume NULL
820 static const struct dev_pm_ops tegra_asoc_machine_pm_ops = {
821 .prepare = snd_soc_suspend,
822 .complete = tegra_asoc_machine_resume,
823 .poweroff = snd_soc_poweroff,
826 static struct platform_driver tegra_asoc_machine_driver = {
829 .owner = THIS_MODULE,
830 .pm = &tegra_asoc_machine_pm_ops,
831 .of_match_table = tegra_machine_of_match,
833 .probe = tegra_machine_driver_probe,
834 .remove = tegra_machine_driver_remove,
836 module_platform_driver(tegra_asoc_machine_driver);
838 MODULE_AUTHOR("Mohan Kumar <mkumard@nvidia.com>, Sameer Pujar <spujar@nvidia.com>");
839 MODULE_DESCRIPTION("Tegra ASoC machine driver");
840 MODULE_LICENSE("GPL");
841 MODULE_ALIAS("platform:" DRV_NAME);
842 MODULE_DEVICE_TABLE(of, tegra_machine_of_match);