GNU Linux-libre 5.19-rc6-gnu
[releases.git] / sound / soc / amd / acp / acp-mach-common.c
1 // SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause)
2 //
3 // This file is provided under a dual BSD/GPLv2 license. When using or
4 // redistributing this file, you may do so under either license.
5 //
6 // Copyright(c) 2021 Advanced Micro Devices, Inc.
7 //
8 // Authors: Ajit Kumar Pandey <AjitKumar.Pandey@amd.com>
9 //          Vijendar Mukunda <Vijendar.Mukunda@amd.com>
10 //
11
12 /*
13  * Machine Driver Interface for ACP HW block
14  */
15
16 #include <sound/core.h>
17 #include <sound/jack.h>
18 #include <sound/pcm_params.h>
19 #include <sound/soc-dapm.h>
20 #include <sound/soc.h>
21 #include <linux/input.h>
22 #include <linux/module.h>
23
24 #include "../../codecs/rt5682.h"
25 #include "../../codecs/rt1019.h"
26 #include "../../codecs/rt5682s.h"
27 #include "acp-mach.h"
28
29 #define PCO_PLAT_CLK 48000000
30 #define RT5682_PLL_FREQ (48000 * 512)
31 #define DUAL_CHANNEL    2
32 #define FOUR_CHANNEL    4
33
34 static struct snd_soc_jack pco_jack;
35
36 static const unsigned int channels[] = {
37         DUAL_CHANNEL,
38 };
39
40 static const unsigned int rates[] = {
41         48000,
42 };
43
44 static const struct snd_pcm_hw_constraint_list constraints_rates = {
45         .count = ARRAY_SIZE(rates),
46         .list  = rates,
47         .mask = 0,
48 };
49
50 static const struct snd_pcm_hw_constraint_list constraints_channels = {
51         .count = ARRAY_SIZE(channels),
52         .list = channels,
53         .mask = 0,
54 };
55
56 static int acp_clk_enable(struct acp_card_drvdata *drvdata)
57 {
58         clk_set_rate(drvdata->wclk, 48000);
59         clk_set_rate(drvdata->bclk, 48000 * 64);
60
61         return clk_prepare_enable(drvdata->wclk);
62 }
63
64 /* Declare RT5682 codec components */
65 SND_SOC_DAILINK_DEF(rt5682,
66         DAILINK_COMP_ARRAY(COMP_CODEC("i2c-10EC5682:00", "rt5682-aif1")));
67
68 static const struct snd_soc_dapm_route rt5682_map[] = {
69         { "Headphone Jack", NULL, "HPOL" },
70         { "Headphone Jack", NULL, "HPOR" },
71         { "IN1P", NULL, "Headset Mic" },
72 };
73
74 /* Define card ops for RT5682 CODEC */
75 static int acp_card_rt5682_init(struct snd_soc_pcm_runtime *rtd)
76 {
77         struct snd_soc_card *card = rtd->card;
78         struct acp_card_drvdata *drvdata = card->drvdata;
79         struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
80         struct snd_soc_component *component = codec_dai->component;
81         int ret;
82
83         dev_info(rtd->dev, "codec dai name = %s\n", codec_dai->name);
84
85         if (drvdata->hs_codec_id != RT5682)
86                 return -EINVAL;
87
88         ret =  snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
89                                    | SND_SOC_DAIFMT_CBP_CFP);
90         if (ret < 0) {
91                 dev_err(rtd->card->dev, "Failed to set dai fmt: %d\n", ret);
92                 return ret;
93         }
94
95         ret = snd_soc_dai_set_pll(codec_dai, RT5682_PLL2, RT5682_PLL2_S_MCLK,
96                                   PCO_PLAT_CLK, RT5682_PLL_FREQ);
97         if (ret < 0) {
98                 dev_err(rtd->dev, "Failed to set codec PLL: %d\n", ret);
99                 return ret;
100         }
101
102         ret = snd_soc_dai_set_sysclk(codec_dai, RT5682_SCLK_S_PLL2,
103                                      RT5682_PLL_FREQ, SND_SOC_CLOCK_IN);
104         if (ret < 0) {
105                 dev_err(rtd->dev, "Failed to set codec SYSCLK: %d\n", ret);
106                 return ret;
107         }
108
109         /* Set tdm/i2s1 master bclk ratio */
110         ret = snd_soc_dai_set_bclk_ratio(codec_dai, 64);
111         if (ret < 0) {
112                 dev_err(rtd->dev, "Failed to set rt5682 tdm bclk ratio: %d\n", ret);
113                 return ret;
114         }
115
116         drvdata->wclk = clk_get(component->dev, "rt5682-dai-wclk");
117         drvdata->bclk = clk_get(component->dev, "rt5682-dai-bclk");
118
119         ret = snd_soc_card_jack_new(card, "Headset Jack",
120                                     SND_JACK_HEADSET | SND_JACK_LINEOUT |
121                                     SND_JACK_BTN_0 | SND_JACK_BTN_1 |
122                                     SND_JACK_BTN_2 | SND_JACK_BTN_3,
123                                     &pco_jack);
124         if (ret) {
125                 dev_err(card->dev, "HP jack creation failed %d\n", ret);
126                 return ret;
127         }
128
129         snd_jack_set_key(pco_jack.jack, SND_JACK_BTN_0, KEY_PLAYPAUSE);
130         snd_jack_set_key(pco_jack.jack, SND_JACK_BTN_1, KEY_VOICECOMMAND);
131         snd_jack_set_key(pco_jack.jack, SND_JACK_BTN_2, KEY_VOLUMEUP);
132         snd_jack_set_key(pco_jack.jack, SND_JACK_BTN_3, KEY_VOLUMEDOWN);
133
134         ret = snd_soc_component_set_jack(component, &pco_jack, NULL);
135         if (ret) {
136                 dev_err(rtd->dev, "Headset Jack call-back failed: %d\n", ret);
137                 return ret;
138         }
139
140         return snd_soc_dapm_add_routes(&rtd->card->dapm, rt5682_map, ARRAY_SIZE(rt5682_map));
141 }
142
143 static int acp_card_hs_startup(struct snd_pcm_substream *substream)
144 {
145         struct snd_pcm_runtime *runtime = substream->runtime;
146         struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
147         struct snd_soc_card *card = rtd->card;
148         struct acp_card_drvdata *drvdata = card->drvdata;
149         struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
150         int ret;
151
152         ret =  snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
153                                    | SND_SOC_DAIFMT_CBP_CFP);
154         if (ret < 0) {
155                 dev_err(rtd->card->dev, "Failed to set dai fmt: %d\n", ret);
156                 return ret;
157         }
158
159         runtime->hw.channels_max = DUAL_CHANNEL;
160         snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
161                                       &constraints_channels);
162         snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
163                                       &constraints_rates);
164
165         ret = acp_clk_enable(drvdata);
166         if (ret < 0)
167                 dev_err(rtd->card->dev, "Failed to enable HS clk: %d\n", ret);
168
169         return ret;
170 }
171
172 static void acp_card_shutdown(struct snd_pcm_substream *substream)
173 {
174         struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
175         struct snd_soc_card *card = rtd->card;
176         struct acp_card_drvdata *drvdata = card->drvdata;
177
178         clk_disable_unprepare(drvdata->wclk);
179 }
180
181 static const struct snd_soc_ops acp_card_rt5682_ops = {
182         .startup = acp_card_hs_startup,
183         .shutdown = acp_card_shutdown,
184 };
185
186 /* Define RT5682S CODEC component*/
187 SND_SOC_DAILINK_DEF(rt5682s,
188                     DAILINK_COMP_ARRAY(COMP_CODEC("i2c-RTL5682:00", "rt5682s-aif1")));
189
190 static const struct snd_soc_dapm_route rt5682s_map[] = {
191         { "Headphone Jack", NULL, "HPOL" },
192         { "Headphone Jack", NULL, "HPOR" },
193         { "IN1P", NULL, "Headset Mic" },
194 };
195
196 static int acp_card_rt5682s_init(struct snd_soc_pcm_runtime *rtd)
197 {
198         struct snd_soc_card *card = rtd->card;
199         struct acp_card_drvdata *drvdata = card->drvdata;
200         struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
201         struct snd_soc_component *component = codec_dai->component;
202         int ret;
203
204         dev_info(rtd->dev, "codec dai name = %s\n", codec_dai->name);
205
206         if (drvdata->hs_codec_id != RT5682S)
207                 return -EINVAL;
208
209         ret =  snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
210                                    | SND_SOC_DAIFMT_CBP_CFP);
211         if (ret < 0) {
212                 dev_err(rtd->card->dev, "Failed to set dai fmt: %d\n", ret);
213                 return ret;
214         }
215
216         ret = snd_soc_dai_set_pll(codec_dai, RT5682S_PLL2, RT5682S_PLL_S_MCLK,
217                                   PCO_PLAT_CLK, RT5682_PLL_FREQ);
218         if (ret < 0) {
219                 dev_err(rtd->dev, "Failed to set codec PLL: %d\n", ret);
220                 return ret;
221         }
222
223         ret = snd_soc_dai_set_sysclk(codec_dai, RT5682S_SCLK_S_PLL2,
224                                      RT5682_PLL_FREQ, SND_SOC_CLOCK_IN);
225         if (ret < 0) {
226                 dev_err(rtd->dev, "Failed to set codec SYSCLK: %d\n", ret);
227                 return ret;
228         }
229
230         /* Set tdm/i2s1 master bclk ratio */
231         ret = snd_soc_dai_set_bclk_ratio(codec_dai, 64);
232         if (ret < 0) {
233                 dev_err(rtd->dev, "Failed to set rt5682 tdm bclk ratio: %d\n", ret);
234                 return ret;
235         }
236
237         drvdata->wclk = clk_get(component->dev, "rt5682-dai-wclk");
238         drvdata->bclk = clk_get(component->dev, "rt5682-dai-bclk");
239
240         ret = snd_soc_card_jack_new(card, "Headset Jack",
241                                     SND_JACK_HEADSET | SND_JACK_LINEOUT |
242                                     SND_JACK_BTN_0 | SND_JACK_BTN_1 |
243                                     SND_JACK_BTN_2 | SND_JACK_BTN_3,
244                                     &pco_jack);
245         if (ret) {
246                 dev_err(card->dev, "HP jack creation failed %d\n", ret);
247                 return ret;
248         }
249
250         snd_jack_set_key(pco_jack.jack, SND_JACK_BTN_0, KEY_PLAYPAUSE);
251         snd_jack_set_key(pco_jack.jack, SND_JACK_BTN_1, KEY_VOICECOMMAND);
252         snd_jack_set_key(pco_jack.jack, SND_JACK_BTN_2, KEY_VOLUMEUP);
253         snd_jack_set_key(pco_jack.jack, SND_JACK_BTN_3, KEY_VOLUMEDOWN);
254
255         ret = snd_soc_component_set_jack(component, &pco_jack, NULL);
256         if (ret) {
257                 dev_err(rtd->dev, "Headset Jack call-back failed: %d\n", ret);
258                 return ret;
259         }
260
261         return snd_soc_dapm_add_routes(&rtd->card->dapm, rt5682s_map, ARRAY_SIZE(rt5682s_map));
262 }
263
264 static const struct snd_soc_ops acp_card_rt5682s_ops = {
265         .startup = acp_card_hs_startup,
266         .shutdown = acp_card_shutdown,
267 };
268
269 static const unsigned int dmic_channels[] = {
270         DUAL_CHANNEL, FOUR_CHANNEL,
271 };
272
273 static const struct snd_pcm_hw_constraint_list dmic_constraints_channels = {
274         .count = ARRAY_SIZE(dmic_channels),
275         .list = dmic_channels,
276         .mask = 0,
277 };
278
279 static int acp_card_dmic_startup(struct snd_pcm_substream *substream)
280 {
281         struct snd_pcm_runtime *runtime = substream->runtime;
282
283         snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
284                                    &dmic_constraints_channels);
285         snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
286                                    &constraints_rates);
287
288         return 0;
289 }
290
291 static const struct snd_soc_ops acp_card_dmic_ops = {
292         .startup = acp_card_dmic_startup,
293 };
294
295 /* Declare RT1019 codec components */
296 SND_SOC_DAILINK_DEF(rt1019,
297         DAILINK_COMP_ARRAY(COMP_CODEC("i2c-10EC1019:00", "rt1019-aif"),
298                           COMP_CODEC("i2c-10EC1019:01", "rt1019-aif")));
299
300 static const struct snd_soc_dapm_route rt1019_map_lr[] = {
301         { "Left Spk", NULL, "Left SPO" },
302         { "Right Spk", NULL, "Right SPO" },
303 };
304
305 static struct snd_soc_codec_conf rt1019_conf[] = {
306         {
307                  .dlc = COMP_CODEC_CONF("i2c-10EC1019:01"),
308                  .name_prefix = "Left",
309         },
310         {
311                  .dlc = COMP_CODEC_CONF("i2c-10EC1019:00"),
312                  .name_prefix = "Right",
313         },
314 };
315
316 static int acp_card_rt1019_init(struct snd_soc_pcm_runtime *rtd)
317 {
318         struct snd_soc_card *card = rtd->card;
319         struct acp_card_drvdata *drvdata = card->drvdata;
320
321         if (drvdata->amp_codec_id != RT1019)
322                 return -EINVAL;
323
324         return snd_soc_dapm_add_routes(&rtd->card->dapm, rt1019_map_lr,
325                                        ARRAY_SIZE(rt1019_map_lr));
326 }
327
328 static int acp_card_rt1019_hw_params(struct snd_pcm_substream *substream,
329                                      struct snd_pcm_hw_params *params)
330 {
331         struct snd_soc_pcm_runtime *rtd = substream->private_data;
332         struct snd_soc_card *card = rtd->card;
333         struct acp_card_drvdata *drvdata = card->drvdata;
334         struct snd_soc_dai *codec_dai;
335         int srate, i, ret = 0;
336
337         srate = params_rate(params);
338
339         if (drvdata->amp_codec_id != RT1019)
340                 return -EINVAL;
341
342         for_each_rtd_codec_dais(rtd, i, codec_dai) {
343                 if (strcmp(codec_dai->name, "rt1019-aif"))
344                         continue;
345
346                 ret = snd_soc_dai_set_pll(codec_dai, 0, RT1019_PLL_S_BCLK,
347                                           64 * srate, 256 * srate);
348                 if (ret < 0)
349                         return ret;
350
351                 ret = snd_soc_dai_set_sysclk(codec_dai, RT1019_SCLK_S_PLL,
352                                              256 * srate, SND_SOC_CLOCK_IN);
353                 if (ret < 0)
354                         return ret;
355         }
356
357         return 0;
358 }
359
360 static int acp_card_amp_startup(struct snd_pcm_substream *substream)
361 {
362         struct snd_pcm_runtime *runtime = substream->runtime;
363         struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
364         struct snd_soc_card *card = rtd->card;
365         struct acp_card_drvdata *drvdata = card->drvdata;
366         int ret;
367
368         runtime->hw.channels_max = DUAL_CHANNEL;
369         snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
370                                       &constraints_channels);
371         snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
372                                       &constraints_rates);
373
374         ret = acp_clk_enable(drvdata);
375         if (ret < 0)
376                 dev_err(rtd->card->dev, "Failed to enable AMP clk: %d\n", ret);
377
378         return ret;
379 }
380
381 static const struct snd_soc_ops acp_card_rt1019_ops = {
382         .startup = acp_card_amp_startup,
383         .shutdown = acp_card_shutdown,
384         .hw_params = acp_card_rt1019_hw_params,
385 };
386
387 /* Declare Maxim codec components */
388 SND_SOC_DAILINK_DEF(max98360a,
389         DAILINK_COMP_ARRAY(COMP_CODEC("MX98360A:00", "HiFi")));
390
391 static const struct snd_soc_dapm_route max98360a_map[] = {
392         {"Spk", NULL, "Speaker"},
393 };
394
395 static int acp_card_maxim_init(struct snd_soc_pcm_runtime *rtd)
396 {
397         struct snd_soc_card *card = rtd->card;
398         struct acp_card_drvdata *drvdata = card->drvdata;
399
400         if (drvdata->amp_codec_id != MAX98360A)
401                 return -EINVAL;
402
403         return snd_soc_dapm_add_routes(&rtd->card->dapm, max98360a_map,
404                                        ARRAY_SIZE(max98360a_map));
405 }
406
407 static const struct snd_soc_ops acp_card_maxim_ops = {
408         .startup = acp_card_amp_startup,
409         .shutdown = acp_card_shutdown,
410 };
411
412 /* Declare DMIC codec components */
413 SND_SOC_DAILINK_DEF(dmic_codec,
414                 DAILINK_COMP_ARRAY(COMP_CODEC("dmic-codec", "dmic-hifi")));
415
416 /* Declare ACP CPU components */
417 static struct snd_soc_dai_link_component dummy_codec[] = {
418         {
419                 .name = "snd-soc-dummy",
420                 .dai_name = "snd-soc-dummy-dai",
421         }
422 };
423
424 static struct snd_soc_dai_link_component platform_component[] = {
425         {
426                  .name = "acp_asoc_renoir.0",
427         }
428 };
429
430 static struct snd_soc_dai_link_component sof_component[] = {
431         {
432                  .name = "0000:04:00.5",
433         }
434 };
435
436 SND_SOC_DAILINK_DEF(i2s_sp,
437         DAILINK_COMP_ARRAY(COMP_CPU("acp-i2s-sp")));
438 SND_SOC_DAILINK_DEF(sof_sp,
439         DAILINK_COMP_ARRAY(COMP_CPU("acp-sof-sp")));
440 SND_SOC_DAILINK_DEF(sof_dmic,
441         DAILINK_COMP_ARRAY(COMP_CPU("acp-sof-dmic")));
442 SND_SOC_DAILINK_DEF(pdm_dmic,
443         DAILINK_COMP_ARRAY(COMP_CPU("acp-pdm-dmic")));
444
445 int acp_sofdsp_dai_links_create(struct snd_soc_card *card)
446 {
447         struct snd_soc_dai_link *links;
448         struct device *dev = card->dev;
449         struct acp_card_drvdata *drv_data = card->drvdata;
450         int i = 0, num_links = 0;
451
452         if (drv_data->hs_cpu_id)
453                 num_links++;
454         if (drv_data->amp_cpu_id)
455                 num_links++;
456         if (drv_data->dmic_cpu_id)
457                 num_links++;
458
459         links = devm_kzalloc(dev, sizeof(struct snd_soc_dai_link) * num_links, GFP_KERNEL);
460         if (!links)
461                 return -ENOMEM;
462
463         if (drv_data->hs_cpu_id == I2S_SP) {
464                 links[i].name = "acp-headset-codec";
465                 links[i].id = HEADSET_BE_ID;
466                 links[i].cpus = sof_sp;
467                 links[i].num_cpus = ARRAY_SIZE(sof_sp);
468                 links[i].platforms = sof_component;
469                 links[i].num_platforms = ARRAY_SIZE(sof_component);
470                 links[i].dpcm_playback = 1;
471                 links[i].dpcm_capture = 1;
472                 links[i].nonatomic = true;
473                 links[i].no_pcm = 1;
474                 if (!drv_data->hs_codec_id) {
475                         /* Use dummy codec if codec id not specified */
476                         links[i].codecs = dummy_codec;
477                         links[i].num_codecs = ARRAY_SIZE(dummy_codec);
478                 }
479                 if (drv_data->hs_codec_id == RT5682) {
480                         links[i].codecs = rt5682;
481                         links[i].num_codecs = ARRAY_SIZE(rt5682);
482                         links[i].init = acp_card_rt5682_init;
483                         links[i].ops = &acp_card_rt5682_ops;
484                 }
485                 if (drv_data->hs_codec_id == RT5682S) {
486                         links[i].codecs = rt5682s;
487                         links[i].num_codecs = ARRAY_SIZE(rt5682s);
488                         links[i].init = acp_card_rt5682s_init;
489                         links[i].ops = &acp_card_rt5682s_ops;
490                 }
491                 i++;
492         }
493
494         if (drv_data->amp_cpu_id == I2S_SP) {
495                 links[i].name = "acp-amp-codec";
496                 links[i].id = AMP_BE_ID;
497                 links[i].cpus = sof_sp;
498                 links[i].num_cpus = ARRAY_SIZE(sof_sp);
499                 links[i].platforms = sof_component;
500                 links[i].num_platforms = ARRAY_SIZE(sof_component);
501                 links[i].dpcm_playback = 1;
502                 links[i].nonatomic = true;
503                 links[i].no_pcm = 1;
504                 if (!drv_data->amp_codec_id) {
505                         /* Use dummy codec if codec id not specified */
506                         links[i].codecs = dummy_codec;
507                         links[i].num_codecs = ARRAY_SIZE(dummy_codec);
508                 }
509                 if (drv_data->amp_codec_id == RT1019) {
510                         links[i].codecs = rt1019;
511                         links[i].num_codecs = ARRAY_SIZE(rt1019);
512                         links[i].ops = &acp_card_rt1019_ops;
513                         links[i].init = acp_card_rt1019_init;
514                         card->codec_conf = rt1019_conf;
515                         card->num_configs = ARRAY_SIZE(rt1019_conf);
516                 }
517                 if (drv_data->amp_codec_id == MAX98360A) {
518                         links[i].codecs = max98360a;
519                         links[i].num_codecs = ARRAY_SIZE(max98360a);
520                         links[i].ops = &acp_card_maxim_ops;
521                         links[i].init = acp_card_maxim_init;
522                 }
523                 i++;
524         }
525
526         if (drv_data->dmic_cpu_id == DMIC) {
527                 links[i].name = "acp-dmic-codec";
528                 links[i].id = DMIC_BE_ID;
529                 links[i].codecs = dmic_codec;
530                 links[i].num_codecs = ARRAY_SIZE(dmic_codec);
531                 links[i].cpus = sof_dmic;
532                 links[i].num_cpus = ARRAY_SIZE(sof_dmic);
533                 links[i].platforms = sof_component;
534                 links[i].num_platforms = ARRAY_SIZE(sof_component);
535                 links[i].dpcm_capture = 1;
536                 links[i].nonatomic = true;
537                 links[i].no_pcm = 1;
538         }
539
540         card->dai_link = links;
541         card->num_links = num_links;
542
543         return 0;
544 }
545 EXPORT_SYMBOL_NS_GPL(acp_sofdsp_dai_links_create, SND_SOC_AMD_MACH);
546
547 int acp_legacy_dai_links_create(struct snd_soc_card *card)
548 {
549         struct snd_soc_dai_link *links;
550         struct device *dev = card->dev;
551         struct acp_card_drvdata *drv_data = card->drvdata;
552         int i = 0, num_links = 0;
553
554         if (drv_data->hs_cpu_id)
555                 num_links++;
556         if (drv_data->amp_cpu_id)
557                 num_links++;
558         if (drv_data->dmic_cpu_id)
559                 num_links++;
560
561         links = devm_kzalloc(dev, sizeof(struct snd_soc_dai_link) * num_links, GFP_KERNEL);
562         if (!links)
563                 return -ENOMEM;
564
565         if (drv_data->hs_cpu_id == I2S_SP) {
566                 links[i].name = "acp-headset-codec";
567                 links[i].id = HEADSET_BE_ID;
568                 links[i].cpus = i2s_sp;
569                 links[i].num_cpus = ARRAY_SIZE(i2s_sp);
570                 links[i].platforms = platform_component;
571                 links[i].num_platforms = ARRAY_SIZE(platform_component);
572                 links[i].dpcm_playback = 1;
573                 links[i].dpcm_capture = 1;
574                 if (!drv_data->hs_codec_id) {
575                         /* Use dummy codec if codec id not specified */
576                         links[i].codecs = dummy_codec;
577                         links[i].num_codecs = ARRAY_SIZE(dummy_codec);
578                 }
579                 if (drv_data->hs_codec_id == RT5682) {
580                         links[i].codecs = rt5682;
581                         links[i].num_codecs = ARRAY_SIZE(rt5682);
582                         links[i].init = acp_card_rt5682_init;
583                         links[i].ops = &acp_card_rt5682_ops;
584                 }
585                 if (drv_data->hs_codec_id == RT5682S) {
586                         links[i].codecs = rt5682s;
587                         links[i].num_codecs = ARRAY_SIZE(rt5682s);
588                         links[i].init = acp_card_rt5682s_init;
589                         links[i].ops = &acp_card_rt5682s_ops;
590                 }
591                 i++;
592         }
593
594         if (drv_data->amp_cpu_id == I2S_SP) {
595                 links[i].name = "acp-amp-codec";
596                 links[i].id = AMP_BE_ID;
597                 links[i].cpus = i2s_sp;
598                 links[i].num_cpus = ARRAY_SIZE(i2s_sp);
599                 links[i].platforms = platform_component;
600                 links[i].num_platforms = ARRAY_SIZE(platform_component);
601                 links[i].dpcm_playback = 1;
602                 if (!drv_data->amp_codec_id) {
603                         /* Use dummy codec if codec id not specified */
604                         links[i].codecs = dummy_codec;
605                         links[i].num_codecs = ARRAY_SIZE(dummy_codec);
606                 }
607                 if (drv_data->amp_codec_id == RT1019) {
608                         links[i].codecs = rt1019;
609                         links[i].num_codecs = ARRAY_SIZE(rt1019);
610                         links[i].ops = &acp_card_rt1019_ops;
611                         links[i].init = acp_card_rt1019_init;
612                         card->codec_conf = rt1019_conf;
613                         card->num_configs = ARRAY_SIZE(rt1019_conf);
614                 }
615                 if (drv_data->amp_codec_id == MAX98360A) {
616                         links[i].codecs = max98360a;
617                         links[i].num_codecs = ARRAY_SIZE(max98360a);
618                         links[i].ops = &acp_card_maxim_ops;
619                         links[i].init = acp_card_maxim_init;
620                 }
621                 i++;
622         }
623
624         if (drv_data->dmic_cpu_id == DMIC) {
625                 links[i].name = "acp-dmic-codec";
626                 links[i].id = DMIC_BE_ID;
627                 if (drv_data->dmic_codec_id == DMIC) {
628                         links[i].codecs = dmic_codec;
629                         links[i].num_codecs = ARRAY_SIZE(dmic_codec);
630                 } else {
631                         /* Use dummy codec if codec id not specified */
632                         links[i].codecs = dummy_codec;
633                         links[i].num_codecs = ARRAY_SIZE(dummy_codec);
634                 }
635                 links[i].cpus = pdm_dmic;
636                 links[i].num_cpus = ARRAY_SIZE(pdm_dmic);
637                 links[i].platforms = platform_component;
638                 links[i].num_platforms = ARRAY_SIZE(platform_component);
639                 links[i].ops = &acp_card_dmic_ops;
640                 links[i].dpcm_capture = 1;
641         }
642
643         card->dai_link = links;
644         card->num_links = num_links;
645
646         return 0;
647 }
648 EXPORT_SYMBOL_NS_GPL(acp_legacy_dai_links_create, SND_SOC_AMD_MACH);
649
650 MODULE_LICENSE("GPL v2");