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
acp_clk_enable(struct acp_card_drvdata * drvdata)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 */
acp_card_rt5682_init(struct snd_soc_pcm_runtime * rtd)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, NULL, 0);
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
acp_card_hs_startup(struct snd_pcm_substream * substream)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
acp_card_shutdown(struct snd_pcm_substream * substream)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
acp_card_rt5682s_init(struct snd_soc_pcm_runtime * rtd)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, NULL, 0);
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 /* Declare RT1019 codec components */
270 SND_SOC_DAILINK_DEF(rt1019,
271 DAILINK_COMP_ARRAY(COMP_CODEC("i2c-10EC1019:01", "rt1019-aif"),
272 COMP_CODEC("i2c-10EC1019:02", "rt1019-aif")));
273
274 static const struct snd_soc_dapm_route rt1019_map_lr[] = {
275 { "Left Spk", NULL, "Left SPO" },
276 { "Right Spk", NULL, "Right SPO" },
277 };
278
279 static struct snd_soc_codec_conf rt1019_conf[] = {
280 {
281 .dlc = COMP_CODEC_CONF("i2c-10EC1019:01"),
282 .name_prefix = "Left",
283 },
284 {
285 .dlc = COMP_CODEC_CONF("i2c-10EC1019:02"),
286 .name_prefix = "Right",
287 },
288 };
289
acp_card_rt1019_init(struct snd_soc_pcm_runtime * rtd)290 static int acp_card_rt1019_init(struct snd_soc_pcm_runtime *rtd)
291 {
292 struct snd_soc_card *card = rtd->card;
293 struct acp_card_drvdata *drvdata = card->drvdata;
294
295 if (drvdata->amp_codec_id != RT1019)
296 return -EINVAL;
297
298 return snd_soc_dapm_add_routes(&rtd->card->dapm, rt1019_map_lr,
299 ARRAY_SIZE(rt1019_map_lr));
300 }
301
acp_card_rt1019_hw_params(struct snd_pcm_substream * substream,struct snd_pcm_hw_params * params)302 static int acp_card_rt1019_hw_params(struct snd_pcm_substream *substream,
303 struct snd_pcm_hw_params *params)
304 {
305 struct snd_soc_pcm_runtime *rtd = substream->private_data;
306 struct snd_soc_card *card = rtd->card;
307 struct acp_card_drvdata *drvdata = card->drvdata;
308 struct snd_soc_dai *codec_dai;
309 int srate, i, ret = 0;
310
311 srate = params_rate(params);
312
313 if (drvdata->amp_codec_id != RT1019)
314 return -EINVAL;
315
316 for_each_rtd_codec_dais(rtd, i, codec_dai) {
317 if (strcmp(codec_dai->name, "rt1019-aif"))
318 continue;
319
320 ret = snd_soc_dai_set_pll(codec_dai, 0, RT1019_PLL_S_BCLK,
321 64 * srate, 256 * srate);
322 if (ret < 0)
323 return ret;
324
325 ret = snd_soc_dai_set_sysclk(codec_dai, RT1019_SCLK_S_PLL,
326 256 * srate, SND_SOC_CLOCK_IN);
327 if (ret < 0)
328 return ret;
329 }
330
331 return 0;
332 }
333
acp_card_amp_startup(struct snd_pcm_substream * substream)334 static int acp_card_amp_startup(struct snd_pcm_substream *substream)
335 {
336 struct snd_pcm_runtime *runtime = substream->runtime;
337 struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
338 struct snd_soc_card *card = rtd->card;
339 struct acp_card_drvdata *drvdata = card->drvdata;
340 int ret;
341
342 runtime->hw.channels_max = DUAL_CHANNEL;
343 snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
344 &constraints_channels);
345 snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
346 &constraints_rates);
347
348 ret = acp_clk_enable(drvdata);
349 if (ret < 0)
350 dev_err(rtd->card->dev, "Failed to enable AMP clk: %d\n", ret);
351
352 return ret;
353 }
354
355 static const struct snd_soc_ops acp_card_rt1019_ops = {
356 .startup = acp_card_amp_startup,
357 .shutdown = acp_card_shutdown,
358 .hw_params = acp_card_rt1019_hw_params,
359 };
360
361 /* Declare Maxim codec components */
362 SND_SOC_DAILINK_DEF(max98360a,
363 DAILINK_COMP_ARRAY(COMP_CODEC("MX98360A:00", "HiFi")));
364
365 static const struct snd_soc_dapm_route max98360a_map[] = {
366 {"Spk", NULL, "Speaker"},
367 };
368
acp_card_maxim_init(struct snd_soc_pcm_runtime * rtd)369 static int acp_card_maxim_init(struct snd_soc_pcm_runtime *rtd)
370 {
371 struct snd_soc_card *card = rtd->card;
372 struct acp_card_drvdata *drvdata = card->drvdata;
373
374 if (drvdata->amp_codec_id != MAX98360A)
375 return -EINVAL;
376
377 return snd_soc_dapm_add_routes(&rtd->card->dapm, max98360a_map,
378 ARRAY_SIZE(max98360a_map));
379 }
380
381 static const struct snd_soc_ops acp_card_maxim_ops = {
382 .startup = acp_card_amp_startup,
383 .shutdown = acp_card_shutdown,
384 };
385
386 /* Declare DMIC codec components */
387 SND_SOC_DAILINK_DEF(dmic_codec,
388 DAILINK_COMP_ARRAY(COMP_CODEC("dmic-codec", "dmic-hifi")));
389
390 /* Declare ACP CPU components */
391 static struct snd_soc_dai_link_component dummy_codec[] = {
392 {
393 .name = "snd-soc-dummy",
394 .dai_name = "snd-soc-dummy-dai",
395 }
396 };
397
398 static struct snd_soc_dai_link_component platform_component[] = {
399 {
400 .name = "acp_asoc_renoir.0",
401 }
402 };
403
404 static struct snd_soc_dai_link_component sof_component[] = {
405 {
406 .name = "0000:04:00.5",
407 }
408 };
409
410 SND_SOC_DAILINK_DEF(i2s_sp,
411 DAILINK_COMP_ARRAY(COMP_CPU("acp-i2s-sp")));
412 SND_SOC_DAILINK_DEF(sof_sp,
413 DAILINK_COMP_ARRAY(COMP_CPU("acp-sof-sp")));
414 SND_SOC_DAILINK_DEF(sof_dmic,
415 DAILINK_COMP_ARRAY(COMP_CPU("acp-sof-dmic")));
416
acp_sofdsp_dai_links_create(struct snd_soc_card * card)417 int acp_sofdsp_dai_links_create(struct snd_soc_card *card)
418 {
419 struct snd_soc_dai_link *links;
420 struct device *dev = card->dev;
421 struct acp_card_drvdata *drv_data = card->drvdata;
422 int i = 0, num_links = 0;
423
424 if (drv_data->hs_cpu_id)
425 num_links++;
426 if (drv_data->amp_cpu_id)
427 num_links++;
428 if (drv_data->dmic_cpu_id)
429 num_links++;
430
431 links = devm_kzalloc(dev, sizeof(struct snd_soc_dai_link) * num_links, GFP_KERNEL);
432 if (!links)
433 return -ENOMEM;
434
435 if (drv_data->hs_cpu_id == I2S_SP) {
436 links[i].name = "acp-headset-codec";
437 links[i].id = HEADSET_BE_ID;
438 links[i].cpus = sof_sp;
439 links[i].num_cpus = ARRAY_SIZE(sof_sp);
440 links[i].platforms = sof_component;
441 links[i].num_platforms = ARRAY_SIZE(sof_component);
442 links[i].dpcm_playback = 1;
443 links[i].dpcm_capture = 1;
444 links[i].nonatomic = true;
445 links[i].no_pcm = 1;
446 if (!drv_data->hs_codec_id) {
447 /* Use dummy codec if codec id not specified */
448 links[i].codecs = dummy_codec;
449 links[i].num_codecs = ARRAY_SIZE(dummy_codec);
450 }
451 if (drv_data->hs_codec_id == RT5682) {
452 links[i].codecs = rt5682;
453 links[i].num_codecs = ARRAY_SIZE(rt5682);
454 links[i].init = acp_card_rt5682_init;
455 links[i].ops = &acp_card_rt5682_ops;
456 }
457 if (drv_data->hs_codec_id == RT5682S) {
458 links[i].codecs = rt5682s;
459 links[i].num_codecs = ARRAY_SIZE(rt5682s);
460 links[i].init = acp_card_rt5682s_init;
461 links[i].ops = &acp_card_rt5682s_ops;
462 }
463 i++;
464 }
465
466 if (drv_data->amp_cpu_id == I2S_SP) {
467 links[i].name = "acp-amp-codec";
468 links[i].id = AMP_BE_ID;
469 links[i].cpus = sof_sp;
470 links[i].num_cpus = ARRAY_SIZE(sof_sp);
471 links[i].platforms = sof_component;
472 links[i].num_platforms = ARRAY_SIZE(sof_component);
473 links[i].dpcm_playback = 1;
474 links[i].nonatomic = true;
475 links[i].no_pcm = 1;
476 if (!drv_data->amp_codec_id) {
477 /* Use dummy codec if codec id not specified */
478 links[i].codecs = dummy_codec;
479 links[i].num_codecs = ARRAY_SIZE(dummy_codec);
480 }
481 if (drv_data->amp_codec_id == RT1019) {
482 links[i].codecs = rt1019;
483 links[i].num_codecs = ARRAY_SIZE(rt1019);
484 links[i].ops = &acp_card_rt1019_ops;
485 links[i].init = acp_card_rt1019_init;
486 card->codec_conf = rt1019_conf;
487 card->num_configs = ARRAY_SIZE(rt1019_conf);
488 }
489 if (drv_data->amp_codec_id == MAX98360A) {
490 links[i].codecs = max98360a;
491 links[i].num_codecs = ARRAY_SIZE(max98360a);
492 links[i].ops = &acp_card_maxim_ops;
493 links[i].init = acp_card_maxim_init;
494 }
495 i++;
496 }
497
498 if (drv_data->dmic_cpu_id == DMIC) {
499 links[i].name = "acp-dmic-codec";
500 links[i].id = DMIC_BE_ID;
501 links[i].codecs = dmic_codec;
502 links[i].num_codecs = ARRAY_SIZE(dmic_codec);
503 links[i].cpus = sof_dmic;
504 links[i].num_cpus = ARRAY_SIZE(sof_dmic);
505 links[i].platforms = sof_component;
506 links[i].num_platforms = ARRAY_SIZE(sof_component);
507 links[i].dpcm_capture = 1;
508 links[i].nonatomic = true;
509 links[i].no_pcm = 1;
510 }
511
512 card->dai_link = links;
513 card->num_links = num_links;
514
515 return 0;
516 }
517 EXPORT_SYMBOL_NS_GPL(acp_sofdsp_dai_links_create, SND_SOC_AMD_MACH);
518
acp_legacy_dai_links_create(struct snd_soc_card * card)519 int acp_legacy_dai_links_create(struct snd_soc_card *card)
520 {
521 struct snd_soc_dai_link *links;
522 struct device *dev = card->dev;
523 struct acp_card_drvdata *drv_data = card->drvdata;
524 int i = 0, num_links = 0;
525
526 if (drv_data->hs_cpu_id)
527 num_links++;
528 if (drv_data->amp_cpu_id)
529 num_links++;
530 if (drv_data->dmic_cpu_id)
531 num_links++;
532
533 links = devm_kzalloc(dev, sizeof(struct snd_soc_dai_link) * num_links, GFP_KERNEL);
534
535 if (drv_data->hs_cpu_id == I2S_SP) {
536 links[i].name = "acp-headset-codec";
537 links[i].id = HEADSET_BE_ID;
538 links[i].cpus = i2s_sp;
539 links[i].num_cpus = ARRAY_SIZE(i2s_sp);
540 links[i].platforms = platform_component;
541 links[i].num_platforms = ARRAY_SIZE(platform_component);
542 links[i].dpcm_playback = 1;
543 links[i].dpcm_capture = 1;
544 if (!drv_data->hs_codec_id) {
545 /* Use dummy codec if codec id not specified */
546 links[i].codecs = dummy_codec;
547 links[i].num_codecs = ARRAY_SIZE(dummy_codec);
548 }
549 if (drv_data->hs_codec_id == RT5682) {
550 links[i].codecs = rt5682;
551 links[i].num_codecs = ARRAY_SIZE(rt5682);
552 links[i].init = acp_card_rt5682_init;
553 links[i].ops = &acp_card_rt5682_ops;
554 }
555 if (drv_data->hs_codec_id == RT5682S) {
556 links[i].codecs = rt5682s;
557 links[i].num_codecs = ARRAY_SIZE(rt5682s);
558 links[i].init = acp_card_rt5682s_init;
559 links[i].ops = &acp_card_rt5682s_ops;
560 }
561 i++;
562 }
563
564 if (drv_data->amp_cpu_id == I2S_SP) {
565 links[i].name = "acp-amp-codec";
566 links[i].id = AMP_BE_ID;
567 links[i].cpus = i2s_sp;
568 links[i].num_cpus = ARRAY_SIZE(i2s_sp);
569 links[i].platforms = platform_component;
570 links[i].num_platforms = ARRAY_SIZE(platform_component);
571 links[i].dpcm_playback = 1;
572 if (!drv_data->amp_codec_id) {
573 /* Use dummy codec if codec id not specified */
574 links[i].codecs = dummy_codec;
575 links[i].num_codecs = ARRAY_SIZE(dummy_codec);
576 }
577 if (drv_data->amp_codec_id == RT1019) {
578 links[i].codecs = rt1019;
579 links[i].num_codecs = ARRAY_SIZE(rt1019);
580 links[i].ops = &acp_card_rt1019_ops;
581 links[i].init = acp_card_rt1019_init;
582 card->codec_conf = rt1019_conf;
583 card->num_configs = ARRAY_SIZE(rt1019_conf);
584 }
585 if (drv_data->amp_codec_id == MAX98360A) {
586 links[i].codecs = max98360a;
587 links[i].num_codecs = ARRAY_SIZE(max98360a);
588 links[i].ops = &acp_card_maxim_ops;
589 links[i].init = acp_card_maxim_init;
590 }
591 }
592
593 card->dai_link = links;
594 card->num_links = num_links;
595
596 return 0;
597 }
598 EXPORT_SYMBOL_NS_GPL(acp_legacy_dai_links_create, SND_SOC_AMD_MACH);
599
600 MODULE_LICENSE("GPL v2");
601