]> nv-tegra.nvidia Code Review - linux-t18x.git/blob - sound/soc/tegra-alt/tegra_t186ref_alt.c
platform: tegra: rtcpu: prevent speculative load related leak
[linux-t18x.git] / sound / soc / tegra-alt / tegra_t186ref_alt.c
1 /*
2  * tegra_t186ref_alt.c - Tegra t186ref Machine driver
3  *
4  * Copyright (c) 2015 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/slab.h>
23 #include <linux/gpio.h>
24 #include <linux/of_gpio.h>
25 #include <linux/i2c.h>
26
27 #include <sound/core.h>
28 #include <sound/jack.h>
29 #include <sound/pcm.h>
30 #include <sound/pcm_params.h>
31 #include <sound/soc.h>
32 #include "../codecs/ad193x.h"
33
34 #include "tegra_asoc_utils_alt.h"
35 #include "tegra_asoc_machine_alt.h"
36 #include "tegra_asoc_machine_alt_t18x.h"
37 #include "ahub_unit_fpga_clock.h"
38
39 #include <linux/clk.h>
40 #include <linux/clk/tegra.h>
41
42 #define DRV_NAME "tegra-snd-t186ref"
43
44 #define MAX_AMX_SLOT_SIZE 64
45 #define MAX_ADX_SLOT_SIZE 64
46 #define DEFAULT_AMX_SLOT_SIZE 32
47 #define DEFAULT_ADX_SLOT_SIZE 32
48 #define MAX_AMX_NUM 1
49 #define MAX_ADX_NUM 1
50
51 static unsigned int configure_max_codec = 1;
52
53 struct tegra_t186ref_amx_adx_conf {
54         unsigned int num_amx;
55         unsigned int num_adx;
56         unsigned int amx_slot_size[MAX_AMX_NUM];
57         unsigned int adx_slot_size[MAX_ADX_NUM];
58 };
59
60 struct tegra_t186ref {
61         struct tegra_asoc_audio_clock_info audio_clock;
62         struct tegra_t186ref_amx_adx_conf amx_adx_conf;
63         unsigned int num_codec_links;
64         int codec_rate_via_kcontrol;
65 };
66
67 static struct snd_soc_pcm_stream tegra_t186ref_amx_input_params[] = {
68         [0] = {
69                 .formats = SNDRV_PCM_FMTBIT_S16_LE,
70                 .rate_min = 48000,
71                 .rate_max = 48000,
72                 .channels_min = 2,
73                 .channels_max = 2,
74         },
75         [1] = {
76                 .formats = SNDRV_PCM_FMTBIT_S16_LE,
77                 .rate_min = 48000,
78                 .rate_max = 48000,
79                 .channels_min = 2,
80                 .channels_max = 2,
81         },
82         [2] = {
83                 .formats = SNDRV_PCM_FMTBIT_S16_LE,
84                 .rate_min = 48000,
85                 .rate_max = 48000,
86                 .channels_min = 2,
87                 .channels_max = 2,
88         },
89         [3] = {
90                 .formats = SNDRV_PCM_FMTBIT_S16_LE,
91                 .rate_min = 48000,
92                 .rate_max = 48000,
93                 .channels_min = 2,
94                 .channels_max = 2,
95         },
96 };
97
98 static struct snd_soc_pcm_stream tegra_t186ref_amx_output_params[] = {
99         [0] = {
100                 .formats = SNDRV_PCM_FMTBIT_S32_LE,
101                 .rate_min = 48000,
102                 .rate_max = 48000,
103                 .channels_min = 8,
104                 .channels_max = 8,
105         },
106 };
107
108 static struct snd_soc_pcm_stream tegra_t186ref_adx_output_params[] = {
109         [0] = {
110                 .formats = SNDRV_PCM_FMTBIT_S16_LE,
111                 .rate_min = 48000,
112                 .rate_max = 48000,
113                 .channels_min = 2,
114                 .channels_max = 2,
115         },
116         [1] = {
117                 .formats = SNDRV_PCM_FMTBIT_S16_LE,
118                 .rate_min = 48000,
119                 .rate_max = 48000,
120                 .channels_min = 2,
121                 .channels_max = 2,
122         },
123         [2] = {
124                 .formats = SNDRV_PCM_FMTBIT_S16_LE,
125                 .rate_min = 48000,
126                 .rate_max = 48000,
127                 .channels_min = 2,
128                 .channels_max = 2,
129         },
130         [3] = {
131                 .formats = SNDRV_PCM_FMTBIT_S16_LE,
132                 .rate_min = 48000,
133                 .rate_max = 48000,
134                 .channels_min = 2,
135                 .channels_max = 2,
136         },
137 };
138
139 static const struct snd_soc_pcm_stream tegra_t186ref_adx_input_params[] = {
140         [0] = {
141                 .formats = SNDRV_PCM_FMTBIT_S32_LE,
142                 .rate_min = 48000,
143                 .rate_max = 48000,
144                 .channels_min = 8,
145                 .channels_max = 8,
146         },
147 };
148
149 static const struct snd_soc_pcm_stream tegra_t186ref_asrc_link_params[] = {
150         [0] = {
151                 .formats = SNDRV_PCM_FMTBIT_S32_LE,
152                 .rate_min = 48000,
153                 .rate_max = 48000,
154                 .channels_min = 8,
155                 .channels_max = 8,
156         },
157         [1] = {
158                 .formats = SNDRV_PCM_FMTBIT_S16_LE,
159                 .rate_min = 48000,
160                 .rate_max = 48000,
161                 .channels_min = 2,
162                 .channels_max = 2,
163         },
164         [2] = {
165                 .formats = SNDRV_PCM_FMTBIT_S16_LE,
166                 .rate_min = 48000,
167                 .rate_max = 48000,
168                 .channels_min = 2,
169                 .channels_max = 2,
170         },
171         [3] = {
172                 .formats = SNDRV_PCM_FMTBIT_S16_LE,
173                 .rate_min = 48000,
174                 .rate_max = 48000,
175                 .channels_min = 2,
176                 .channels_max = 2,
177         },
178         [4] = {
179                 .formats = SNDRV_PCM_FMTBIT_S16_LE,
180                 .rate_min = 48000,
181                 .rate_max = 48000,
182                 .channels_min = 2,
183                 .channels_max = 2,
184         },
185         [5] = {
186                 .formats = SNDRV_PCM_FMTBIT_S16_LE,
187                 .rate_min = 48000,
188                 .rate_max = 48000,
189                 .channels_min = 2,
190                 .channels_max = 2,
191         },
192 };
193
194 static const struct snd_soc_pcm_stream tegra_t186ref_arad_link_params = {
195         .formats = SNDRV_PCM_FMTBIT_S24_LE,
196         .rate_min = 48000,
197         .rate_max = 48000,
198         .channels_min = 2,
199         .channels_max = 2,
200 };
201
202 static struct snd_soc_dai_link
203         tegra186_arad_dai_links[1] = {
204         [0] = {
205                 .name = "ARAD1 TX",
206                 .stream_name = "ARAD1 TX",
207                 .cpu_dai_name = "ARAD OUT",
208                 .codec_dai_name = "ARAD1",
209                 .cpu_name = "tegra186-arad",
210                 .codec_name = "2900800.ahub",
211                 .params = &tegra_t186ref_arad_link_params,
212         },
213 };
214
215 static int tegra_t186ref_hw_params(struct snd_pcm_substream *substream,
216                                         struct snd_pcm_hw_params *params)
217 {
218         struct snd_soc_pcm_runtime *rtd = substream->private_data;
219         struct snd_soc_card *card = rtd->card;
220
221         int idx = tegra_machine_get_codec_dai_link_idx_t18x("spdif-dit-0");
222         struct snd_soc_pcm_stream *dai_params;
223         int mclk, clk_out_rate;
224         int err;
225
226         /* check if idx has valid number */
227         if (idx == -EINVAL)
228                 return idx;
229
230         dai_params =
231                 (struct snd_soc_pcm_stream *)card->rtd[idx].dai_link->params;
232         switch (dai_params->rate_min) {
233         case 11025:
234         case 22050:
235         case 44100:
236         case 88200:
237         case 176000:
238                 clk_out_rate = 11289600; /* Codec rate */
239                 mclk = 11289600 * 2; /* PLL_A rate */
240                 break;
241         case 8000:
242         case 16000:
243         case 32000:
244         case 48000:
245         case 64000:
246         case 96000:
247         case 192000:
248         default:
249                 clk_out_rate = 12288000;
250                 mclk = 12288000 * 2;
251                 break;
252         }
253
254         err = snd_soc_dai_set_bclk_ratio(card->rtd[idx].cpu_dai,
255                 tegra_machine_get_bclk_ratio_t18x(&card->rtd[idx]));
256         if (err < 0) {
257                 dev_err(card->dev, "Failed to set cpu dai bclk ratio\n");
258                 return err;
259         }
260
261         return 0;
262 }
263 static int tegra_t186ref_startup(struct snd_pcm_substream *substream)
264 {
265         return 0;
266 }
267 static void tegra_t186ref_shutdown(struct snd_pcm_substream *substream)
268 {
269 }
270
271 static int tegra_t186ref_init(struct snd_soc_pcm_runtime *rtd)
272 {
273         struct snd_soc_card *card = rtd->card;
274         struct snd_soc_dai *i2s_dai = rtd->cpu_dai;
275         struct device_node *np =
276                 (struct device_node *)rtd->dai_link->cpu_of_node;
277         struct device_node *parentnp = np->parent;
278         unsigned int fmt = rtd->dai_link->dai_fmt;
279         unsigned int tx_mask = (1<<8) - 1, rx_mask = (1<<8) - 1;
280         AD1937_EXTRA_INFO ad1937_info;
281         int err;
282
283         if (configure_max_codec) {
284                 /* PLL, I2S and Codec programming */
285                 program_cdc_pll(2, CLK_OUT_12_2888_MHZ);
286                 program_cdc_pll(4, CLK_OUT_24_5760_MHZ); /* for I2S3 in slave */
287                 SetMax9485(CLK_OUT_24_5760_MHZ); /* for I2S5 in slave */
288                 program_io_expander();
289                 i2c_clk_divider(10 - 1);
290
291                 /* I2S1 - 8kHz, I2S3/I2S5 - 48kHz */
292                 i2s_clk_divider(I2S1, 23); /* BCLK=512khz, LRCK=8khz */
293                 i2s_clk_divider(I2S3, 0); /* BCLK=12.288khz, LRCK=48khz */
294                 i2s_clk_divider(I2S5, 3); /* BCLK=3.072khz, LRCK=48khz */
295                 /* configure max codec on E1660 */
296                 program_max_codec();
297
298                 /* I2S3 */
299                 ad1937_info.codecId = AD1937_Y_ADDRESS;
300                 ad1937_info.clkgenId = CLK_OUT_FROM_TEGRA;
301                 ad1937_info.dacMasterEn = AUDIO_DAC_SLAVE_MODE;
302                 ad1937_info.daisyEn = 0;
303                 ad1937_info.mclk_mode = AD1937_MCLK_PLL_INTERNAL_MODE;
304                 pr_err("AD1937 addr 0x%x\n", ad1937_info.codecId);
305                 OnAD1937CaptureAndPlayback(AUDIO_CODEC_SLAVE_MODE,
306                                         AUDIO_INTERFACE_TDM_FORMAT,
307                                         I2S_DATAWIDTH_16,
308                                         256, 0, 0,
309                                         AUDIO_SAMPLE_RATE_48_00,
310                                         &ad1937_info);
311
312                 /* I2S5 */
313                 ad1937_info.codecId = AD1937_Z_ADDRESS;
314                 ad1937_info.clkgenId = CLK_OUT_FROM_TEGRA;
315                 ad1937_info.dacMasterEn = AUDIO_DAC_SLAVE_MODE;
316                 ad1937_info.daisyEn = 0;
317                 ad1937_info.mclk_mode = AD1937_MCLK_PLL_INTERNAL_MODE;
318                 pr_err("AD1937 addr 0x%x\n", ad1937_info.codecId);
319                 OnAD1937CaptureAndPlayback(AUDIO_CODEC_SLAVE_MODE,
320                                         AUDIO_INTERFACE_I2S_FORMAT,
321                                         I2S_DATAWIDTH_16,
322                                         64, 0, 0,
323                                         AUDIO_SAMPLE_RATE_48_00,
324                                         &ad1937_info);
325
326                 configure_max_codec = 0;
327         }
328
329         err = snd_soc_dai_set_bclk_ratio(i2s_dai,
330                         tegra_machine_get_bclk_ratio_t18x(rtd));
331         if (err < 0) {
332                 dev_err(card->dev, "Failed to set cpu dai bclk ratio\n");
333                 return err;
334         }
335
336         if (parentnp) {
337                 of_property_read_u32(np, "tx-mask", (u32 *)&tx_mask);
338                 of_property_read_u32(np, "rx-mask", (u32 *)&rx_mask);
339         }
340
341         if ((fmt & SND_SOC_DAIFMT_FORMAT_MASK) == SND_SOC_DAIFMT_DSP_A)
342                 snd_soc_dai_set_tdm_slot(i2s_dai, tx_mask, rx_mask, 0, 0);
343
344         return 0;
345 }
346
347 static int tegra_t186ref_dummy(struct snd_soc_pcm_runtime *rtd)
348 {
349         return 0;
350 }
351
352 static int tegra_t186ref_amx1_dai_init(struct snd_soc_pcm_runtime *rtd)
353 {
354         struct snd_soc_card *card = rtd->card;
355         struct tegra_t186ref *machine = snd_soc_card_get_drvdata(card);
356         struct snd_soc_dai *amx_dai = rtd->cpu_dai;
357         struct device_node *np = rtd->card->dev->of_node;
358         unsigned int tx_slot[MAX_AMX_SLOT_SIZE];
359         unsigned int i, j, default_slot_mode = 0;
360         unsigned int slot_size = machine->amx_adx_conf.amx_slot_size[0];
361
362         if (machine->amx_adx_conf.num_amx && slot_size) {
363                 if (of_property_read_u32_array(np,
364                         "nvidia,amx-slot-map", tx_slot, slot_size))
365                         default_slot_mode = 1;
366         } else
367                 default_slot_mode = 1;
368
369         if (default_slot_mode) {
370                 slot_size = DEFAULT_AMX_SLOT_SIZE;
371                 for (i = 0, j = 0; i < slot_size; i += 8) {
372                         tx_slot[i] = 0;
373                         tx_slot[i + 1] = 0;
374                         tx_slot[i + 2] = (j << 16) | (1 << 8) | 0;
375                         tx_slot[i + 3] = (j << 16) | (1 << 8) | 1;
376                         tx_slot[i + 4] = 0;
377                         tx_slot[i + 5] = 0;
378                         tx_slot[i + 6] = (j << 16) | (2 << 8) | 0;
379                         tx_slot[i + 7] = (j << 16) | (2 << 8) | 1;
380                         j++;
381                 }
382         }
383
384         if (amx_dai->driver->ops->set_channel_map)
385                 amx_dai->driver->ops->set_channel_map(amx_dai,
386                         slot_size, tx_slot, 0, NULL);
387
388         return 0;
389 }
390 static int tegra_t186ref_adx1_dai_init(struct snd_soc_pcm_runtime *rtd)
391 {
392         struct snd_soc_card *card = rtd->card;
393         struct tegra_t186ref *machine = snd_soc_card_get_drvdata(card);
394         struct snd_soc_dai *adx_dai = rtd->codec_dai;
395         struct device_node *np = rtd->card->dev->of_node;
396         unsigned int rx_slot[MAX_ADX_SLOT_SIZE];
397         unsigned int i, j, default_slot_mode = 0;
398         unsigned int slot_size = machine->amx_adx_conf.adx_slot_size[0];
399
400         if (machine->amx_adx_conf.num_adx && slot_size) {
401                 if (of_property_read_u32_array(np,
402                         "nvidia,adx-slot-map", rx_slot, slot_size))
403                         default_slot_mode = 1;
404         } else
405                 default_slot_mode = 1;
406
407         if (default_slot_mode) {
408                 slot_size = DEFAULT_ADX_SLOT_SIZE;
409                 for (i = 0, j = 0; i < slot_size; i += 8) {
410                         rx_slot[i] = 0;
411                         rx_slot[i + 1] = 0;
412                         rx_slot[i + 2] = (j << 16) | (1 << 8) | 0;
413                         rx_slot[i + 3] = (j << 16) | (1 << 8) | 1;
414                         rx_slot[i + 4] = 0;
415                         rx_slot[i + 5] = 0;
416                         rx_slot[i + 6] = (j << 16) | (2 << 8) | 0;
417                         rx_slot[i + 7] = (j << 16) | (2 << 8) | 1;
418                         j++;
419                 }
420         }
421
422         if (adx_dai->driver->ops->set_channel_map)
423                 adx_dai->driver->ops->set_channel_map(adx_dai,
424                         0, NULL, slot_size, rx_slot);
425
426         return 0;
427 }
428
429 static int tegra_t186ref_sfc_init(struct snd_soc_pcm_runtime *rtd)
430 {
431         struct snd_soc_dai *codec_dai = rtd->codec_dai;
432         unsigned int in_srate, out_srate;
433         int err;
434
435         in_srate = 8000;
436         out_srate = 48000;
437
438         err = snd_soc_dai_set_sysclk(codec_dai, 0, out_srate,
439                                         SND_SOC_CLOCK_OUT);
440         err = snd_soc_dai_set_sysclk(codec_dai, 0, in_srate,
441                                         SND_SOC_CLOCK_IN);
442
443         return 0;
444 }
445
446 static struct snd_soc_ops tegra_t186ref_ops = {
447         .hw_params = tegra_t186ref_hw_params,
448         .startup = tegra_t186ref_startup,
449         .shutdown = tegra_t186ref_shutdown,
450 };
451
452 static const struct snd_soc_dapm_widget tegra_t186ref_dapm_widgets[] = {
453         SND_SOC_DAPM_HP("Headphone-x", NULL),
454         SND_SOC_DAPM_HP("Headphone-y", NULL),
455         SND_SOC_DAPM_LINE("LineIn-x", NULL),
456         SND_SOC_DAPM_LINE("LineIn-y", NULL),
457 };
458
459 static const struct snd_soc_dapm_route tegra_t186ref_audio_map[] = {
460 };
461
462 static const int tegra_t186ref_srate_values[] = {
463         0,
464         8000,
465         16000,
466         44100,
467         48000,
468         11025,
469         22050,
470         24000,
471         32000,
472         88200,
473         96000,
474         176000,
475         192000,
476 };
477
478 static const char * const tegra_t186ref_srate_text[] = {
479         "None",
480         "8kHz",
481         "16kHz",
482         "44kHz",
483         "48kHz",
484         "11kHz",
485         "22kHz",
486         "24kHz",
487         "32kHz",
488         "88kHz",
489         "96kHz",
490         "176kHz",
491         "192kHz",
492 };
493
494 static int tegra_t186ref_codec_get_rate(struct snd_kcontrol *kcontrol,
495         struct snd_ctl_elem_value *ucontrol)
496 {
497         struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
498         struct tegra_t186ref *machine = snd_soc_card_get_drvdata(card);
499
500         ucontrol->value.integer.value[0] = machine->codec_rate_via_kcontrol;
501
502         return 0;
503 }
504
505 static int tegra_t186ref_codec_put_rate(struct snd_kcontrol *kcontrol,
506         struct snd_ctl_elem_value *ucontrol)
507 {
508         struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
509         struct tegra_t186ref *machine = snd_soc_card_get_drvdata(card);
510         unsigned int idx =
511                 tegra_machine_get_codec_dai_link_idx_t18x("spdif-dit-0");
512         struct snd_soc_pcm_stream *dai_params =
513                 (struct snd_soc_pcm_stream *)card->dai_link[idx].params;
514
515         /* set the rate control flag */
516         machine->codec_rate_via_kcontrol = ucontrol->value.integer.value[0];
517
518         /* update the dai params rate */
519         dai_params->rate_min =
520                 tegra_t186ref_srate_values[machine->codec_rate_via_kcontrol];
521
522         return 0;
523 }
524
525 static int tegra_t186ref_remove(struct snd_soc_card *card)
526 {
527         return 0;
528 }
529
530 static const struct soc_enum tegra_t186ref_codec_rate =
531         SOC_ENUM_SINGLE_EXT(13, tegra_t186ref_srate_text);
532
533 static const struct snd_kcontrol_new tegra_t186ref_controls[] = {
534         SOC_ENUM_EXT("codec-x rate", tegra_t186ref_codec_rate,
535                 tegra_t186ref_codec_get_rate,
536                 tegra_t186ref_codec_put_rate),
537 };
538
539
540 static struct snd_soc_card snd_soc_tegra_t186ref = {
541         .name = "tegra-t186ref",
542         .owner = THIS_MODULE,
543         .remove = tegra_t186ref_remove,
544         .dapm_widgets = tegra_t186ref_dapm_widgets,
545         .num_dapm_widgets = ARRAY_SIZE(tegra_t186ref_dapm_widgets),
546         .controls = tegra_t186ref_controls,
547         .num_controls = ARRAY_SIZE(tegra_t186ref_controls),
548         .fully_routed = true,
549 };
550
551 static int tegra_t186ref_driver_probe(struct platform_device *pdev)
552 {
553         struct device_node *np = pdev->dev.of_node;
554         struct snd_soc_card *card = &snd_soc_tegra_t186ref;
555         struct tegra_t186ref *machine;
556         struct snd_soc_dai_link *tegra_machine_dai_links = NULL;
557         struct snd_soc_dai_link *tegra_t186ref_codec_links = NULL;
558         struct snd_soc_codec_conf *tegra_machine_codec_conf = NULL;
559         struct snd_soc_codec_conf *tegra_t186ref_codec_conf = NULL;
560         int ret = 0, i, j;
561
562         /* TODO : Remove ahub_unit_fpga_init() on the silicon bringup */
563         ahub_unit_fpga_init();
564
565         machine = devm_kzalloc(&pdev->dev, sizeof(struct tegra_t186ref),
566                                GFP_KERNEL);
567         if (!machine) {
568                 dev_err(&pdev->dev, "Can't allocate tegra_t186ref struct\n");
569                 ret = -ENOMEM;
570                 goto err;
571         }
572
573         card->dev = &pdev->dev;
574         platform_set_drvdata(pdev, card);
575         snd_soc_card_set_drvdata(card, machine);
576
577         if (np) {
578                 ret = snd_soc_of_parse_card_name(card, "nvidia,model");
579                 if (ret)
580                         goto err;
581
582                 ret = snd_soc_of_parse_audio_routing(card,
583                                         "nvidia,audio-routing");
584                 if (ret)
585                         goto err;
586         }
587
588         if (of_property_read_u32(np, "nvidia,num-amx",
589                 (u32 *)&machine->amx_adx_conf.num_amx))
590                 machine->amx_adx_conf.num_amx = 0;
591         if (of_property_read_u32_array(np, "nvidia,amx-slot-size",
592                 (u32 *)machine->amx_adx_conf.amx_slot_size,
593                 MAX_AMX_NUM) || !machine->amx_adx_conf.num_amx) {
594                 for (i = 0; i < MAX_AMX_NUM; i++)
595                         machine->amx_adx_conf.amx_slot_size[i] = 0;
596         }
597
598         if (of_property_read_u32(np, "nvidia,num-adx",
599                 (u32 *)&machine->amx_adx_conf.num_adx))
600                 machine->amx_adx_conf.num_adx = 0;
601         if (of_property_read_u32_array(np, "nvidia,adx-slot-size",
602                 (u32 *)machine->amx_adx_conf.adx_slot_size,
603                 MAX_ADX_NUM) || !machine->amx_adx_conf.num_adx) {
604                 for (i = 0; i < MAX_ADX_NUM; i++)
605                         machine->amx_adx_conf.adx_slot_size[i] = 0;
606         }
607
608         /* set new codec links and conf */
609         tegra_t186ref_codec_links = tegra_machine_new_codec_links(pdev,
610                 tegra_t186ref_codec_links,
611                 &machine->num_codec_links);
612         if (!tegra_t186ref_codec_links)
613                 goto err_alloc_dai_link;
614
615         tegra_t186ref_codec_conf = tegra_machine_new_codec_conf(pdev,
616                 tegra_t186ref_codec_conf,
617                 &machine->num_codec_links);
618         if (!tegra_t186ref_codec_conf)
619                 goto err_alloc_dai_link;
620
621         /* get the xbar dai link/codec conf structure */
622         tegra_machine_dai_links = tegra_machine_get_dai_link_t18x();
623         if (!tegra_machine_dai_links)
624                 goto err_alloc_dai_link;
625
626         tegra_machine_codec_conf = tegra_machine_get_codec_conf_t18x();
627         if (!tegra_machine_codec_conf)
628                 goto err_alloc_dai_link;
629
630         /* set AMX/ADX dai_init */
631         tegra_machine_set_dai_init(TEGRA186_DAI_LINK_AMX1,
632                 &tegra_t186ref_amx1_dai_init);
633         tegra_machine_set_dai_init(TEGRA186_DAI_LINK_ADX1,
634                 &tegra_t186ref_adx1_dai_init);
635
636         /* set codec init */
637         for (i = 0; i < machine->num_codec_links; i++) {
638                 if (tegra_t186ref_codec_links[i].codec_of_node->name) {
639                         if (strstr(tegra_t186ref_codec_links[i].name,
640                                 "spdif-dit-0"))
641                                 tegra_t186ref_codec_links[i].init =
642                                         tegra_t186ref_init;
643                         else if (strstr(tegra_t186ref_codec_links[i].name,
644                                 "spdif-dit-1"))
645                                 tegra_t186ref_codec_links[i].init =
646                                         tegra_t186ref_dummy;
647                 }
648         }
649
650         /* set AMX/ADX params */
651         if (machine->amx_adx_conf.num_amx) {
652                 switch (machine->amx_adx_conf.num_amx) {
653                 case 1:
654                         tegra_machine_set_dai_params(TEGRA186_DAI_LINK_AMX1_1,
655                                 (struct snd_soc_pcm_stream *)
656                                 &tegra_t186ref_amx_input_params[0]);
657                         tegra_machine_set_dai_params(TEGRA186_DAI_LINK_AMX1_2,
658                                 (struct snd_soc_pcm_stream *)
659                                 &tegra_t186ref_amx_input_params[1]);
660                         tegra_machine_set_dai_params(TEGRA186_DAI_LINK_AMX1_3,
661                                 (struct snd_soc_pcm_stream *)
662                                 &tegra_t186ref_amx_input_params[2]);
663                         tegra_machine_set_dai_params(TEGRA186_DAI_LINK_AMX1_4,
664                                 (struct snd_soc_pcm_stream *)
665                                 &tegra_t186ref_amx_input_params[3]);
666                         tegra_machine_set_dai_params(TEGRA186_DAI_LINK_AMX1,
667                                 (struct snd_soc_pcm_stream *)
668                                 &tegra_t186ref_amx_output_params[0]);
669                         break;
670                 default:
671                         break;
672                 }
673         }
674
675         if (machine->amx_adx_conf.num_adx) {
676                 switch (machine->amx_adx_conf.num_adx) {
677                 case 1:
678                         tegra_machine_set_dai_params(TEGRA186_DAI_LINK_ADX1_1,
679                                 (struct snd_soc_pcm_stream *)
680                                 &tegra_t186ref_adx_output_params[0]);
681                         tegra_machine_set_dai_params(TEGRA186_DAI_LINK_ADX1_2,
682                                 (struct snd_soc_pcm_stream *)
683                                 &tegra_t186ref_adx_output_params[1]);
684                         tegra_machine_set_dai_params(TEGRA186_DAI_LINK_ADX1_3,
685                                 (struct snd_soc_pcm_stream *)
686                                 &tegra_t186ref_adx_output_params[2]);
687                         tegra_machine_set_dai_params(TEGRA186_DAI_LINK_ADX1_4,
688                                 (struct snd_soc_pcm_stream *)
689                                 &tegra_t186ref_adx_output_params[3]);
690                         tegra_machine_set_dai_params(TEGRA186_DAI_LINK_ADX1,
691                                 (struct snd_soc_pcm_stream *)
692                                 &tegra_t186ref_adx_input_params[0]);
693                         break;
694                 default:
695                         break;
696                 }
697         }
698
699         /* set ASRC params. The default is 2 channels */
700         for (i = 0; i < 6; i++) {
701                 tegra_machine_set_dai_params(TEGRA186_DAI_LINK_ASRC1_TX1 + i,
702                         (struct snd_soc_pcm_stream *)
703                                 &tegra_t186ref_asrc_link_params[i]);
704                 tegra_machine_set_dai_params(TEGRA186_DAI_LINK_ASRC1_RX1 + i,
705                         (struct snd_soc_pcm_stream *)
706                                 &tegra_t186ref_asrc_link_params[i]);
707         }
708
709         /* The packet from ARAD to ASRC for the ratio update is 24 bit */
710         tegra_machine_set_dai_params(TEGRA186_DAI_LINK_ASRC1_RX7,
711                                 (struct snd_soc_pcm_stream *)
712                                 &tegra_t186ref_arad_link_params);
713
714         /* set ADMAIF dai_ops */
715         for (i = TEGRA186_DAI_LINK_ADMAIF1;
716                 i <= TEGRA186_DAI_LINK_ADMAIF20; i++)
717                 tegra_machine_set_dai_ops(i, &tegra_t186ref_ops);
718
719         for (i = 0; i < machine->num_codec_links; i++) {
720                 if (tegra_t186ref_codec_links[i].name) {
721                         if (strstr(tegra_t186ref_codec_links[i].name,
722                                 "spdif-dit-0")) {
723                                 for (j = TEGRA186_DAI_LINK_ADMAIF1;
724                                         j <= TEGRA186_DAI_LINK_ADMAIF20; j++)
725                                         tegra_machine_set_dai_ops(j,
726                                                 &tegra_t186ref_ops);
727                         }
728                 }
729         }
730
731         /* set sfc dai_init */
732         tegra_machine_set_dai_init(TEGRA186_DAI_LINK_SFC1_RX,
733                 &tegra_t186ref_sfc_init);
734
735         /* append t186ref specific dai_links */
736         card->num_links =
737                 tegra_machine_append_dai_link_t18x(tegra_t186ref_codec_links,
738                         2 * machine->num_codec_links);
739         card->num_links =
740                 tegra_machine_append_dai_link_t18x(tegra186_arad_dai_links,
741                         1);
742
743         tegra_machine_dai_links = tegra_machine_get_dai_link_t18x();
744         card->dai_link = tegra_machine_dai_links;
745
746         /* append t186ref specific codec_conf */
747         card->num_configs =
748                 tegra_machine_append_codec_conf_t18x(tegra_t186ref_codec_conf,
749                         machine->num_codec_links);
750         tegra_machine_codec_conf = tegra_machine_get_codec_conf_t18x();
751         card->codec_conf = tegra_machine_codec_conf;
752
753         ret = snd_soc_register_card(card);
754         if (ret) {
755                 dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n",
756                         ret);
757                 goto err_fini_utils;
758         }
759
760         return 0;
761
762 err_fini_utils:
763         tegra_alt_asoc_utils_fini(&machine->audio_clock);
764 err_alloc_dai_link:
765         tegra_machine_remove_dai_link();
766         tegra_machine_remove_codec_conf();
767 err:
768         ahub_unit_fpga_deinit();
769         return ret;
770 }
771
772 static int tegra_t186ref_driver_remove(struct platform_device *pdev)
773 {
774         struct snd_soc_card *card = platform_get_drvdata(pdev);
775         struct tegra_t186ref *machine = snd_soc_card_get_drvdata(card);
776
777         ahub_unit_fpga_deinit();
778         snd_soc_unregister_card(card);
779
780         tegra_machine_remove_dai_link();
781         tegra_alt_asoc_utils_fini(&machine->audio_clock);
782
783         return 0;
784 }
785
786 static const struct of_device_id tegra_t186ref_of_match[] = {
787         { .compatible = "nvidia,tegra-audio-t186ref", },
788         {},
789 };
790
791 static struct platform_driver tegra_t186ref_driver = {
792         .driver = {
793                 .name = DRV_NAME,
794                 .owner = THIS_MODULE,
795                 .pm = &snd_soc_pm_ops,
796                 .of_match_table = tegra_t186ref_of_match,
797         },
798         .probe = tegra_t186ref_driver_probe,
799         .remove = tegra_t186ref_driver_remove,
800 };
801 module_platform_driver(tegra_t186ref_driver);
802
803 MODULE_AUTHOR("Junghyun Kim <juskim@nvidia.com>");
804 MODULE_DESCRIPTION("Tegra T186 machine ASoC driver");
805 MODULE_LICENSE("GPL");
806 MODULE_ALIAS("platform:" DRV_NAME);
807 MODULE_DEVICE_TABLE(of, tegra_t186ref_of_match);