]> nv-tegra.nvidia Code Review - linux-nvidia.git/blob - sound/soc/tegra-alt/machine_drivers/tegra_machine_driver_mobile.c
platform: tegra: mc: add option to disable L3 alloc hint from mss nvlink
[linux-nvidia.git] / sound / soc / tegra-alt / machine_drivers / tegra_machine_driver_mobile.c
1 /*
2  * tegra_machine_driver_mobile.c - Tegra ASoC Machine driver for mobile
3  *
4  * Copyright (c) 2017-2021 NVIDIA CORPORATION.  All rights reserved.
5  *
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.
9  *
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
13  * more details.
14  *
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/>.
17  */
18
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>
31 #include "rt5659.h"
32 #include "sgtl5000.h"
33 #include "tegra_asoc_machine_alt.h"
34 #include "tegra210_xbar_alt.h"
35
36 #define DRV_NAME "tegra-asoc:"
37
38 #define PARAMS(sformat, channels)               \
39         {                                       \
40                 .formats = sformat,             \
41                 .rate_min = 48000,              \
42                 .rate_max = 48000,              \
43                 .channels_min = channels,       \
44                 .channels_max = channels,       \
45         }
46
47 /* t210 soc data */
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,
56 #endif
57         .sfc_dai_link                   = TEGRA210_DAI_LINK_SFC1_RX,
58
59         .write_idle_bias_off_state      = false,
60
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,
65 };
66
67 /* t186 soc data */
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,
76 #endif
77         .sfc_dai_link                   = TEGRA186_DAI_LINK_SFC1_RX,
78
79         .write_idle_bias_off_state      = true,
80
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,
85 };
86
87 static const char * const tegra_machine_srate_text[] = {
88         "None",
89         "8kHz",
90         "16kHz",
91         "44kHz",
92         "48kHz",
93         "11kHz",
94         "22kHz",
95         "24kHz",
96         "32kHz",
97         "88kHz",
98         "96kHz",
99         "176kHz",
100         "192kHz",
101 };
102
103 static const char * const tegra_machine_format_text[] = {
104         "None",
105         "16",
106         "32",
107 };
108
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);
112
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);
116
117 static const int tegra_machine_srate_values[] = {
118         0,
119         8000,
120         16000,
121         44100,
122         48000,
123         11025,
124         22050,
125         24000,
126         32000,
127         88200,
128         96000,
129         176400,
130         192000,
131 };
132
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),
138
139         SND_SOC_DAPM_SPK("d1 Headphone", NULL),
140         SND_SOC_DAPM_SPK("d2 Headphone", NULL),
141         SND_SOC_DAPM_SPK("d3 Headphone", NULL),
142
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),
152
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),
167
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),
172 };
173
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),
181 };
182
183 static int tegra_machine_codec_get_rate(struct snd_kcontrol *kcontrol,
184                                         struct snd_ctl_elem_value *ucontrol)
185 {
186         struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
187         struct tegra_machine *machine = snd_soc_card_get_drvdata(card);
188
189         ucontrol->value.integer.value[0] = machine->rate_via_kcontrol;
190
191         return 0;
192 }
193
194 static int tegra_machine_codec_put_rate(struct snd_kcontrol *kcontrol,
195                                         struct snd_ctl_elem_value *ucontrol)
196 {
197         struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
198         struct tegra_machine *machine = snd_soc_card_get_drvdata(card);
199
200         /* set the rate control flag */
201         machine->rate_via_kcontrol = ucontrol->value.integer.value[0];
202
203         return 0;
204 }
205
206 static int tegra_machine_codec_get_format(struct snd_kcontrol *kcontrol,
207         struct snd_ctl_elem_value *ucontrol)
208 {
209         struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
210         struct tegra_machine *machine = snd_soc_card_get_drvdata(card);
211
212         ucontrol->value.integer.value[0] = machine->fmt_via_kcontrol;
213
214         return 0;
215 }
216
217 static int tegra_machine_codec_put_format(struct snd_kcontrol *kcontrol,
218         struct snd_ctl_elem_value *ucontrol)
219 {
220         struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
221         struct tegra_machine *machine = snd_soc_card_get_drvdata(card);
222
223         /* set the format control flag */
224         machine->fmt_via_kcontrol = ucontrol->value.integer.value[0];
225
226         return 0;
227 }
228
229 static int tegra_machine_set_params(struct snd_soc_card *card,
230                                     struct tegra_machine *machine,
231                                     unsigned int rate,
232                                     unsigned int channels,
233                                     u64 formats)
234 {
235         unsigned int mask = (1 << channels) - 1;
236         struct snd_soc_pcm_runtime *rtd;
237         int idx = 0, err = 0;
238         u64 format_k;
239
240         int num_of_dai_links = machine->soc_data->num_ahub_links +
241                                machine->num_codec_links;
242
243         format_k = (machine->fmt_via_kcontrol == 2) ?
244                         (1ULL << SNDRV_PCM_FORMAT_S32_LE) : formats;
245
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;
250
251                         dai_params =
252                           (struct snd_soc_pcm_stream *)
253                           rtd->dai_link->params;
254
255                         dai_params->rate_min = rate;
256                         dai_params->channels_min = channels;
257                         dai_params->formats = format_k;
258
259                         if ((idx >= machine->soc_data->num_ahub_links)
260                                 && (idx < num_of_dai_links)) {
261                                 unsigned int fmt;
262
263                                 /* TODO: why below overrite is needed */
264                                 dai_params->formats = formats;
265
266                                 fmt = rtd->dai_link->dai_fmt;
267                                 fmt &= SND_SOC_DAIFMT_FORMAT_MASK;
268
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(
273                                                         rtd->cpu_dai, mask,
274                                                         mask, 0, 0);
275                                         if (err < 0) {
276                                                 dev_err(card->dev,
277                                                 "%s cpu DAI slot mask not set\n",
278                                                 rtd->cpu_dai->name);
279                                                 return err;
280                                         }
281                                 }
282                         }
283                 }
284                 idx++;
285         }
286         return 0;
287 }
288
289 static int tegra_machine_dai_init(struct snd_soc_pcm_runtime *runtime,
290                                   unsigned int rate, unsigned int channels,
291                                   u64 formats)
292 {
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;
299
300         srate = (machine->rate_via_kcontrol) ?
301                         tegra_machine_srate_values[machine->rate_via_kcontrol] :
302                         rate;
303
304         switch (formats) {
305         case SNDRV_PCM_FORMAT_S8:
306                 sample_size = 8;
307                 break;
308         case SNDRV_PCM_FORMAT_S16_LE:
309                 sample_size = 16;
310                 break;
311         case SNDRV_PCM_FORMAT_S24_LE:
312         /*
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.
319          */
320         case SNDRV_PCM_FORMAT_S32_LE:
321                 sample_size = 32;
322                 break;
323         default:
324                 pr_err("Wrong format!\n");
325                 return -EINVAL;
326         }
327         formats = 1ULL << formats;
328
329         err = tegra_alt_asoc_utils_set_rate(&machine->audio_clock, srate,
330                                                 channels, sample_size, 0, 0);
331         if (err < 0) {
332                 dev_err(card->dev, "Can't configure clocks\n");
333                 return err;
334         }
335
336         aud_mclk = machine->audio_clock.set_aud_mclk_rate;
337
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);
340
341         err = tegra_machine_set_params(card, machine, srate, channels, formats);
342         if (err < 0)
343                 return err;
344
345         rtd = snd_soc_get_pcm_runtime(card, "rt565x-playback");
346         if (rtd) {
347                 dai_params =
348                 (struct snd_soc_pcm_stream *)rtd->dai_link->params;
349
350                 dai_params->formats = (machine->fmt_via_kcontrol == 2) ?
351                         (1ULL << SNDRV_PCM_FORMAT_S32_LE) : formats;
352
353                 err = snd_soc_dai_set_sysclk(rtd->codec_dai, RT5659_SCLK_S_MCLK,
354                                              aud_mclk, SND_SOC_CLOCK_IN);
355                 if (err < 0) {
356                         dev_err(card->dev, "codec_dai clock not set\n");
357                         return err;
358                 }
359         }
360
361         rtd = snd_soc_get_pcm_runtime(card, "rt565x-codec-sysclk-bclk1");
362         if (rtd) {
363                 dai_params =
364                 (struct snd_soc_pcm_stream *)rtd->dai_link->params;
365
366                 dai_params->formats = (machine->fmt_via_kcontrol == 2) ?
367                         (1ULL << SNDRV_PCM_FORMAT_S32_LE) : formats;
368
369                 err = rt565x_manage_codec_sysclk(dai_params, rtd->codec_dai,
370                                                  RT5659_PLL1_S_BCLK1);
371                 if (err < 0) {
372                         dev_err(card->dev, "codec_dai clock not set\n");
373                         return err;
374                 }
375         }
376
377
378         rtd = snd_soc_get_pcm_runtime(card, "dspk-playback-r");
379         if (rtd) {
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,
383                                 SND_SOC_CLOCK_IN);
384                         if (err < 0) {
385                                 dev_err(card->dev, "codec_dai clock not set\n");
386                                 return err;
387                         }
388                 }
389         }
390
391         rtd = snd_soc_get_pcm_runtime(card, "dspk-playback-l");
392         if (rtd) {
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,
396                                 SND_SOC_CLOCK_IN);
397                         if (err < 0) {
398                                 dev_err(card->dev, "codec_dai clock not set\n");
399                                 return err;
400                         }
401                 }
402         }
403
404         return 0;
405 }
406
407 static int tegra_machine_pcm_hw_params(struct snd_pcm_substream *substream,
408                                         struct snd_pcm_hw_params *params)
409 {
410         struct snd_soc_pcm_runtime *rtd = substream->private_data;
411         struct snd_soc_card *card = rtd->card;
412         int err;
413
414         err = tegra_machine_dai_init(rtd, params_rate(params),
415                                      params_channels(params),
416                                      params_format(params));
417         if (err < 0) {
418                 dev_err(card->dev, "Failed dai init\n");
419                 return err;
420         }
421
422         return 0;
423 }
424
425 static int tegra_machine_pcm_startup(struct snd_pcm_substream *substream)
426 {
427         struct snd_soc_pcm_runtime *rtd = substream->private_data;
428         struct tegra_machine *machine = snd_soc_card_get_drvdata(rtd->card);
429
430         tegra_alt_asoc_utils_clk_enable(&machine->audio_clock);
431
432         return 0;
433 }
434
435 static void tegra_machine_pcm_shutdown(struct snd_pcm_substream *substream)
436 {
437         struct snd_soc_pcm_runtime *rtd = substream->private_data;
438         struct tegra_machine *machine = snd_soc_card_get_drvdata(rtd->card);
439
440         tegra_alt_asoc_utils_clk_disable(&machine->audio_clock);
441 }
442
443 static int tegra_machine_suspend_pre(struct snd_soc_card *card)
444 {
445         struct snd_soc_pcm_runtime *rtd;
446
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);
451         }
452
453         return 0;
454 }
455
456 #if IS_ENABLED(CONFIG_SND_SOC_TEGRA210_ADSP_ALT)
457 static int tegra_machine_compr_startup(struct snd_compr_stream *cstream)
458 {
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);
462
463         tegra_alt_asoc_utils_clk_enable(&machine->audio_clock);
464
465         return 0;
466 }
467
468 static void tegra_machine_compr_shutdown(struct snd_compr_stream *cstream)
469 {
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);
473
474         tegra_alt_asoc_utils_clk_disable(&machine->audio_clock);
475 }
476
477 static int tegra_machine_compr_set_params(struct snd_compr_stream *cstream)
478 {
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;
483         int err;
484
485         if (platform->driver->compr_ops &&
486                 platform->driver->compr_ops->get_params) {
487                 err = platform->driver->compr_ops->get_params(cstream,
488                         &codec_params);
489                 if (err < 0) {
490                         dev_err(card->dev, "Failed to get compr params\n");
491                         return err;
492                 }
493         } else {
494                 dev_err(card->dev, "compr ops not set\n");
495                 return -EINVAL;
496         }
497
498         err = tegra_machine_dai_init(rtd, codec_params.sample_rate,
499                                      codec_params.ch_out,
500                                      SNDRV_PCM_FORMAT_S16_LE);
501         if (err < 0) {
502                 dev_err(card->dev, "Failed dai init\n");
503                 return err;
504         }
505
506         return 0;
507 }
508 #endif
509
510 static int tegra_machine_respeaker_init(struct snd_soc_pcm_runtime *rtd)
511 {
512         struct device *dev = rtd->card->dev;
513         int err;
514
515         /* ac108 codec driver hardcodes the freq as 24000000
516          * and source as PLL irrespective of args passed through
517          * this callback
518          */
519         err = snd_soc_dai_set_sysclk(rtd->codec_dai, 0, 24000000,
520                                      SND_SOC_CLOCK_IN);
521         if (err) {
522                 dev_err(dev, "failed to set ac108 sysclk!\n");
523                 return err;
524         }
525
526         return 0;
527 }
528
529 static int tegra_machine_fepi_init(struct snd_soc_pcm_runtime *rtd)
530 {
531         struct device *dev = rtd->card->dev;
532         int err;
533
534         err = snd_soc_dai_set_sysclk(rtd->codec_dai, SGTL5000_SYSCLK, 12288000,
535                                      SND_SOC_CLOCK_IN);
536         if (err) {
537                 dev_err(dev, "failed to set sgtl5000 sysclk!\n");
538                 return err;
539         }
540
541         return 0;
542 }
543
544 static int tegra_machine_rt565x_init(struct snd_soc_pcm_runtime *rtd)
545 {
546         struct snd_soc_card *card = rtd->card;
547         struct snd_soc_jack *jack;
548         int err;
549
550         jack = devm_kzalloc(card->dev, sizeof(struct snd_soc_jack), GFP_KERNEL);
551         if (!jack)
552                 return -ENOMEM;
553
554         err = snd_soc_card_jack_new(card, "Headset Jack", SND_JACK_HEADSET,
555                                     jack, NULL, 0);
556         if (err) {
557                 dev_err(card->dev, "Headset Jack creation failed %d\n", err);
558                 return err;
559         }
560
561         err = tegra_machine_add_codec_jack_control(card, rtd, jack);
562         if (err) {
563                 dev_err(card->dev, "Failed to add jack control: %d\n", err);
564                 return err;
565         }
566
567         err = rt5659_set_jack_detect(rtd->codec, jack);
568         if (err) {
569                 dev_err(card->dev, "Failed to set jack for RT565x: %d\n", err);
570                 return err;
571         }
572
573         /* single button supporting play/pause */
574         snd_jack_set_key(jack->jack, SND_JACK_BTN_0, KEY_MEDIA);
575
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);
580
581         snd_soc_dapm_sync(&card->dapm);
582
583         return 0;
584 }
585
586 static int codec_init(struct tegra_machine *machine)
587 {
588         struct snd_soc_dai_link *dai_links = machine->asoc->dai_links;
589         unsigned int num_links = machine->asoc->num_links, i;
590
591         if (!dai_links || !num_links)
592                 return -EINVAL;
593
594         for (i = 0; i < num_links; i++) {
595                 if (!dai_links[i].name)
596                         continue;
597
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;
605         }
606
607         return 0;
608 }
609
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,
614 };
615
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,
621 };
622 #endif
623
624 static void set_dai_ops(struct tegra_machine *machine)
625 {
626         int i;
627
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;
637         /* set ADSP COMPR */
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;
642 #endif
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;
650
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];
655                 }
656         }
657 #endif
658 }
659
660 static int add_dai_links(struct platform_device *pdev)
661 {
662         struct snd_soc_card *card = platform_get_drvdata(pdev);
663         struct tegra_machine *machine = snd_soc_card_get_drvdata(card);
664         int ret;
665
666         machine->asoc = devm_kzalloc(&pdev->dev, sizeof(*machine->asoc),
667                                      GFP_KERNEL);
668         if (!machine->asoc)
669                 return -ENOMEM;
670
671         ret = tegra_asoc_populate_dai_links(pdev);
672         if (ret < 0)
673                 return ret;
674
675         ret = tegra_asoc_populate_codec_confs(pdev);
676         if (ret < 0)
677                 return ret;
678
679         ret = codec_init(machine);
680         if (ret < 0)
681                 return ret;
682
683         set_dai_ops(machine);
684
685         return 0;
686 }
687
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),
693 };
694
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,
703 };
704
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 },
713         {},
714 };
715
716 static int tegra_machine_driver_probe(struct platform_device *pdev)
717 {
718         struct device_node *np = pdev->dev.of_node;
719         struct snd_soc_card *card = &snd_soc_tegra_card;
720         struct tegra_machine *machine;
721         int ret = 0;
722         const struct of_device_id *match;
723
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");
727         if (ret)
728                 return ret;
729
730         match = of_match_device(tegra_machine_of_match, &pdev->dev);
731         if (!match) {
732                 dev_err(&pdev->dev, "Error: No device match found\n");
733                 return -ENODEV;
734         }
735
736         if (!np) {
737                 dev_err(&pdev->dev, "No DT node for tegra machine driver");
738                 return -ENODEV;
739         }
740
741         machine = devm_kzalloc(&pdev->dev, sizeof(*machine), GFP_KERNEL);
742         if (!machine)
743                 return -ENOMEM;
744
745         machine->soc_data = (struct tegra_machine_soc_data *)match->data;
746         if (!machine->soc_data)
747                 return -EINVAL;
748
749         platform_set_drvdata(pdev, card);
750         snd_soc_card_set_drvdata(card, machine);
751
752         if (machine->soc_data->write_cdev1_state)
753                 machine->audio_clock.clk_cdev1_state = 0;
754
755         if (machine->soc_data->write_idle_bias_off_state)
756                 card->dapm.idle_bias_off = true;
757
758         ret = snd_soc_of_parse_audio_routing(card,
759                                 "nvidia,audio-routing");
760         if (ret)
761                 return ret;
762
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");
767
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");
771         }
772
773         tegra_machine_dma_set_mask(pdev);
774
775         ret = add_dai_links(pdev);
776         if (ret < 0)
777                 goto cleanup_asoc;
778
779         ret = tegra_alt_asoc_utils_init(&machine->audio_clock,
780                                         &pdev->dev,
781                                         card);
782         if (ret < 0)
783                 goto cleanup_asoc;
784
785         ret = snd_soc_register_card(card);
786         if (ret) {
787                 dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n",
788                         ret);
789                 goto cleanup_asoc;
790         }
791
792         tegra_machine_add_i2s_codec_controls(card,
793                                         machine->soc_data->num_ahub_links +
794                                         machine->num_codec_links);
795
796         return 0;
797 cleanup_asoc:
798         release_asoc_phandles(machine);
799         return ret;
800 }
801
802 static int tegra_machine_driver_remove(struct platform_device *pdev)
803 {
804         struct snd_soc_card *card = platform_get_drvdata(pdev);
805
806         snd_soc_unregister_card(card);
807
808         return 0;
809 }
810
811 #if CONFIG_PM
812 static void tegra_asoc_machine_resume(struct device *dev)
813 {
814         WARN_ON(snd_soc_resume(dev));
815 }
816 #else
817 #define tegra_asoc_machine_resume NULL
818 #endif
819
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,
824 };
825
826 static struct platform_driver tegra_asoc_machine_driver = {
827         .driver = {
828                 .name = DRV_NAME,
829                 .owner = THIS_MODULE,
830                 .pm = &tegra_asoc_machine_pm_ops,
831                 .of_match_table = tegra_machine_of_match,
832         },
833         .probe = tegra_machine_driver_probe,
834         .remove = tegra_machine_driver_remove,
835 };
836 module_platform_driver(tegra_asoc_machine_driver);
837
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);