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