xref: /linux/sound/soc/amd/acp/acp-mach-common.c (revision 13a45b9484e58317c95046e5478c0b1d67df8816)
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 "../../codecs/nau8825.h"
28 #include "acp-mach.h"
29 
30 #define PCO_PLAT_CLK 48000000
31 #define RT5682_PLL_FREQ (48000 * 512)
32 #define DUAL_CHANNEL	2
33 #define FOUR_CHANNEL	4
34 
35 static struct snd_soc_jack pco_jack;
36 
37 static const unsigned int channels[] = {
38 	DUAL_CHANNEL,
39 };
40 
41 static const unsigned int rates[] = {
42 	48000,
43 };
44 
45 static const struct snd_pcm_hw_constraint_list constraints_rates = {
46 	.count = ARRAY_SIZE(rates),
47 	.list  = rates,
48 	.mask = 0,
49 };
50 
51 static const struct snd_pcm_hw_constraint_list constraints_channels = {
52 	.count = ARRAY_SIZE(channels),
53 	.list = channels,
54 	.mask = 0,
55 };
56 
57 static int acp_clk_enable(struct acp_card_drvdata *drvdata)
58 {
59 	clk_set_rate(drvdata->wclk, 48000);
60 	clk_set_rate(drvdata->bclk, 48000 * 64);
61 
62 	return clk_prepare_enable(drvdata->wclk);
63 }
64 
65 /* Declare RT5682 codec components */
66 SND_SOC_DAILINK_DEF(rt5682,
67 	DAILINK_COMP_ARRAY(COMP_CODEC("i2c-10EC5682:00", "rt5682-aif1")));
68 
69 static const struct snd_soc_dapm_route rt5682_map[] = {
70 	{ "Headphone Jack", NULL, "HPOL" },
71 	{ "Headphone Jack", NULL, "HPOR" },
72 	{ "IN1P", NULL, "Headset Mic" },
73 };
74 
75 /* Define card ops for RT5682 CODEC */
76 static int acp_card_rt5682_init(struct snd_soc_pcm_runtime *rtd)
77 {
78 	struct snd_soc_card *card = rtd->card;
79 	struct acp_card_drvdata *drvdata = card->drvdata;
80 	struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
81 	struct snd_soc_component *component = codec_dai->component;
82 	int ret;
83 
84 	dev_info(rtd->dev, "codec dai name = %s\n", codec_dai->name);
85 
86 	if (drvdata->hs_codec_id != RT5682)
87 		return -EINVAL;
88 
89 	ret =  snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
90 				   | SND_SOC_DAIFMT_CBP_CFP);
91 	if (ret < 0) {
92 		dev_err(rtd->card->dev, "Failed to set dai fmt: %d\n", ret);
93 		return ret;
94 	}
95 
96 	ret = snd_soc_dai_set_pll(codec_dai, RT5682_PLL2, RT5682_PLL2_S_MCLK,
97 				  PCO_PLAT_CLK, RT5682_PLL_FREQ);
98 	if (ret < 0) {
99 		dev_err(rtd->dev, "Failed to set codec PLL: %d\n", ret);
100 		return ret;
101 	}
102 
103 	ret = snd_soc_dai_set_sysclk(codec_dai, RT5682_SCLK_S_PLL2,
104 				     RT5682_PLL_FREQ, SND_SOC_CLOCK_IN);
105 	if (ret < 0) {
106 		dev_err(rtd->dev, "Failed to set codec SYSCLK: %d\n", ret);
107 		return ret;
108 	}
109 
110 	/* Set tdm/i2s1 master bclk ratio */
111 	ret = snd_soc_dai_set_bclk_ratio(codec_dai, 64);
112 	if (ret < 0) {
113 		dev_err(rtd->dev, "Failed to set rt5682 tdm bclk ratio: %d\n", ret);
114 		return ret;
115 	}
116 
117 	drvdata->wclk = clk_get(component->dev, "rt5682-dai-wclk");
118 	drvdata->bclk = clk_get(component->dev, "rt5682-dai-bclk");
119 
120 	ret = snd_soc_card_jack_new(card, "Headset Jack",
121 				    SND_JACK_HEADSET | SND_JACK_LINEOUT |
122 				    SND_JACK_BTN_0 | SND_JACK_BTN_1 |
123 				    SND_JACK_BTN_2 | SND_JACK_BTN_3,
124 				    &pco_jack);
125 	if (ret) {
126 		dev_err(card->dev, "HP jack creation failed %d\n", ret);
127 		return ret;
128 	}
129 
130 	snd_jack_set_key(pco_jack.jack, SND_JACK_BTN_0, KEY_PLAYPAUSE);
131 	snd_jack_set_key(pco_jack.jack, SND_JACK_BTN_1, KEY_VOICECOMMAND);
132 	snd_jack_set_key(pco_jack.jack, SND_JACK_BTN_2, KEY_VOLUMEUP);
133 	snd_jack_set_key(pco_jack.jack, SND_JACK_BTN_3, KEY_VOLUMEDOWN);
134 
135 	ret = snd_soc_component_set_jack(component, &pco_jack, NULL);
136 	if (ret) {
137 		dev_err(rtd->dev, "Headset Jack call-back failed: %d\n", ret);
138 		return ret;
139 	}
140 
141 	return snd_soc_dapm_add_routes(&rtd->card->dapm, rt5682_map, ARRAY_SIZE(rt5682_map));
142 }
143 
144 static int acp_card_hs_startup(struct snd_pcm_substream *substream)
145 {
146 	struct snd_pcm_runtime *runtime = substream->runtime;
147 	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
148 	struct snd_soc_card *card = rtd->card;
149 	struct acp_card_drvdata *drvdata = card->drvdata;
150 	struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
151 	int ret;
152 	unsigned int fmt;
153 
154 	if (drvdata->soc_mclk)
155 		fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBC_CFC;
156 	else
157 		fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBP_CFP;
158 
159 	ret =  snd_soc_dai_set_fmt(codec_dai, fmt);
160 	if (ret < 0) {
161 		dev_err(rtd->card->dev, "Failed to set dai fmt: %d\n", ret);
162 		return ret;
163 	}
164 
165 	runtime->hw.channels_max = DUAL_CHANNEL;
166 	snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
167 				      &constraints_channels);
168 	snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
169 				      &constraints_rates);
170 	if (!drvdata->soc_mclk) {
171 		ret = acp_clk_enable(drvdata);
172 		if (ret < 0) {
173 			dev_err(rtd->card->dev, "Failed to enable HS clk: %d\n", ret);
174 			return ret;
175 		}
176 	}
177 
178 	return ret;
179 }
180 
181 static void acp_card_shutdown(struct snd_pcm_substream *substream)
182 {
183 	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
184 	struct snd_soc_card *card = rtd->card;
185 	struct acp_card_drvdata *drvdata = card->drvdata;
186 
187 	if (!drvdata->soc_mclk)
188 		clk_disable_unprepare(drvdata->wclk);
189 }
190 
191 static const struct snd_soc_ops acp_card_rt5682_ops = {
192 	.startup = acp_card_hs_startup,
193 	.shutdown = acp_card_shutdown,
194 };
195 
196 /* Define RT5682S CODEC component*/
197 SND_SOC_DAILINK_DEF(rt5682s,
198 		    DAILINK_COMP_ARRAY(COMP_CODEC("i2c-RTL5682:00", "rt5682s-aif1")));
199 
200 static const struct snd_soc_dapm_route rt5682s_map[] = {
201 	{ "Headphone Jack", NULL, "HPOL" },
202 	{ "Headphone Jack", NULL, "HPOR" },
203 	{ "IN1P", NULL, "Headset Mic" },
204 };
205 
206 static int acp_card_rt5682s_init(struct snd_soc_pcm_runtime *rtd)
207 {
208 	struct snd_soc_card *card = rtd->card;
209 	struct acp_card_drvdata *drvdata = card->drvdata;
210 	struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
211 	struct snd_soc_component *component = codec_dai->component;
212 	unsigned int fmt;
213 	int ret;
214 
215 	dev_info(rtd->dev, "codec dai name = %s\n", codec_dai->name);
216 
217 	if (drvdata->hs_codec_id != RT5682S)
218 		return -EINVAL;
219 
220 	if (drvdata->soc_mclk)
221 		fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBC_CFC;
222 	else
223 		fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBP_CFP;
224 
225 	ret =  snd_soc_dai_set_fmt(codec_dai, fmt);
226 	if (ret < 0) {
227 		dev_err(rtd->card->dev, "Failed to set dai fmt: %d\n", ret);
228 		return ret;
229 	}
230 
231 	ret = snd_soc_dai_set_pll(codec_dai, RT5682S_PLL2, RT5682S_PLL_S_MCLK,
232 				  PCO_PLAT_CLK, RT5682_PLL_FREQ);
233 	if (ret < 0) {
234 		dev_err(rtd->dev, "Failed to set codec PLL: %d\n", ret);
235 		return ret;
236 	}
237 
238 	ret = snd_soc_dai_set_sysclk(codec_dai, RT5682S_SCLK_S_PLL2,
239 				     RT5682_PLL_FREQ, SND_SOC_CLOCK_IN);
240 	if (ret < 0) {
241 		dev_err(rtd->dev, "Failed to set codec SYSCLK: %d\n", ret);
242 		return ret;
243 	}
244 
245 	/* Set tdm/i2s1 master bclk ratio */
246 	ret = snd_soc_dai_set_bclk_ratio(codec_dai, 64);
247 	if (ret < 0) {
248 		dev_err(rtd->dev, "Failed to set rt5682 tdm bclk ratio: %d\n", ret);
249 		return ret;
250 	}
251 
252 	if (!drvdata->soc_mclk) {
253 		drvdata->wclk = clk_get(component->dev, "rt5682-dai-wclk");
254 		drvdata->bclk = clk_get(component->dev, "rt5682-dai-bclk");
255 	}
256 
257 	ret = snd_soc_card_jack_new(card, "Headset Jack",
258 				    SND_JACK_HEADSET | SND_JACK_LINEOUT |
259 				    SND_JACK_BTN_0 | SND_JACK_BTN_1 |
260 				    SND_JACK_BTN_2 | SND_JACK_BTN_3,
261 				    &pco_jack);
262 	if (ret) {
263 		dev_err(card->dev, "HP jack creation failed %d\n", ret);
264 		return ret;
265 	}
266 
267 	snd_jack_set_key(pco_jack.jack, SND_JACK_BTN_0, KEY_PLAYPAUSE);
268 	snd_jack_set_key(pco_jack.jack, SND_JACK_BTN_1, KEY_VOICECOMMAND);
269 	snd_jack_set_key(pco_jack.jack, SND_JACK_BTN_2, KEY_VOLUMEUP);
270 	snd_jack_set_key(pco_jack.jack, SND_JACK_BTN_3, KEY_VOLUMEDOWN);
271 
272 	ret = snd_soc_component_set_jack(component, &pco_jack, NULL);
273 	if (ret) {
274 		dev_err(rtd->dev, "Headset Jack call-back failed: %d\n", ret);
275 		return ret;
276 	}
277 
278 	return snd_soc_dapm_add_routes(&rtd->card->dapm, rt5682s_map, ARRAY_SIZE(rt5682s_map));
279 }
280 
281 static const struct snd_soc_ops acp_card_rt5682s_ops = {
282 	.startup = acp_card_hs_startup,
283 	.shutdown = acp_card_shutdown,
284 };
285 
286 static const unsigned int dmic_channels[] = {
287 	DUAL_CHANNEL, FOUR_CHANNEL,
288 };
289 
290 static const struct snd_pcm_hw_constraint_list dmic_constraints_channels = {
291 	.count = ARRAY_SIZE(dmic_channels),
292 	.list = dmic_channels,
293 	.mask = 0,
294 };
295 
296 static int acp_card_dmic_startup(struct snd_pcm_substream *substream)
297 {
298 	struct snd_pcm_runtime *runtime = substream->runtime;
299 
300 	snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
301 				   &dmic_constraints_channels);
302 	snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
303 				   &constraints_rates);
304 
305 	return 0;
306 }
307 
308 static const struct snd_soc_ops acp_card_dmic_ops = {
309 	.startup = acp_card_dmic_startup,
310 };
311 
312 /* Declare RT1019 codec components */
313 SND_SOC_DAILINK_DEF(rt1019,
314 	DAILINK_COMP_ARRAY(COMP_CODEC("i2c-10EC1019:00", "rt1019-aif"),
315 			  COMP_CODEC("i2c-10EC1019:01", "rt1019-aif")));
316 SND_SOC_DAILINK_DEF(rt1019_1,
317 		    DAILINK_COMP_ARRAY(COMP_CODEC("i2c-10EC1019:02", "rt1019-aif"),
318 		    COMP_CODEC("i2c-10EC1019:01", "rt1019-aif")));
319 
320 static const struct snd_soc_dapm_route rt1019_map_lr[] = {
321 	{ "Left Spk", NULL, "Left SPO" },
322 	{ "Right Spk", NULL, "Right SPO" },
323 };
324 
325 static struct snd_soc_codec_conf rt1019_conf[] = {
326 	{
327 		 .dlc = COMP_CODEC_CONF("i2c-10EC1019:01"),
328 		 .name_prefix = "Left",
329 	},
330 	{
331 		 .dlc = COMP_CODEC_CONF("i2c-10EC1019:00"),
332 		 .name_prefix = "Right",
333 	},
334 };
335 
336 static struct snd_soc_codec_conf rt1019_1_conf[] = {
337 	{
338 		.dlc = COMP_CODEC_CONF("i2c-10EC1019:02"),
339 		.name_prefix = "Left",
340 	},
341 	{
342 		.dlc = COMP_CODEC_CONF("i2c-10EC1019:01"),
343 		.name_prefix = "Right",
344 	},
345 };
346 
347 static int acp_card_rt1019_init(struct snd_soc_pcm_runtime *rtd)
348 {
349 	struct snd_soc_card *card = rtd->card;
350 	struct acp_card_drvdata *drvdata = card->drvdata;
351 
352 	if (drvdata->amp_codec_id != RT1019)
353 		return -EINVAL;
354 
355 	return snd_soc_dapm_add_routes(&rtd->card->dapm, rt1019_map_lr,
356 				       ARRAY_SIZE(rt1019_map_lr));
357 }
358 
359 static int acp_card_rt1019_hw_params(struct snd_pcm_substream *substream,
360 				     struct snd_pcm_hw_params *params)
361 {
362 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
363 	struct snd_soc_card *card = rtd->card;
364 	struct acp_card_drvdata *drvdata = card->drvdata;
365 	struct snd_soc_dai *codec_dai;
366 	int srate, i, ret = 0;
367 
368 	srate = params_rate(params);
369 
370 	if (drvdata->amp_codec_id != RT1019)
371 		return -EINVAL;
372 
373 	for_each_rtd_codec_dais(rtd, i, codec_dai) {
374 		if (strcmp(codec_dai->name, "rt1019-aif"))
375 			continue;
376 
377 		ret = snd_soc_dai_set_pll(codec_dai, 0, RT1019_PLL_S_BCLK,
378 					  64 * srate, 256 * srate);
379 		if (ret < 0)
380 			return ret;
381 
382 		ret = snd_soc_dai_set_sysclk(codec_dai, RT1019_SCLK_S_PLL,
383 					     256 * srate, SND_SOC_CLOCK_IN);
384 		if (ret < 0)
385 			return ret;
386 	}
387 
388 	return 0;
389 }
390 
391 static int acp_card_amp_startup(struct snd_pcm_substream *substream)
392 {
393 	struct snd_pcm_runtime *runtime = substream->runtime;
394 	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
395 	struct snd_soc_card *card = rtd->card;
396 	struct acp_card_drvdata *drvdata = card->drvdata;
397 	int ret = 0;
398 
399 	runtime->hw.channels_max = DUAL_CHANNEL;
400 	snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
401 				      &constraints_channels);
402 	snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
403 				      &constraints_rates);
404 
405 	if (!drvdata->soc_mclk) {
406 		ret = acp_clk_enable(drvdata);
407 		if (ret < 0) {
408 			dev_err(rtd->card->dev, "Failed to enable AMP clk: %d\n", ret);
409 			return ret;
410 		}
411 	}
412 	return ret;
413 }
414 
415 static const struct snd_soc_ops acp_card_rt1019_ops = {
416 	.startup = acp_card_amp_startup,
417 	.shutdown = acp_card_shutdown,
418 	.hw_params = acp_card_rt1019_hw_params,
419 };
420 
421 /* Declare Maxim codec components */
422 SND_SOC_DAILINK_DEF(max98360a,
423 	DAILINK_COMP_ARRAY(COMP_CODEC("MX98360A:00", "HiFi")));
424 
425 static const struct snd_soc_dapm_route max98360a_map[] = {
426 	{"Spk", NULL, "Speaker"},
427 };
428 
429 static int acp_card_maxim_init(struct snd_soc_pcm_runtime *rtd)
430 {
431 	struct snd_soc_card *card = rtd->card;
432 	struct acp_card_drvdata *drvdata = card->drvdata;
433 
434 	if (drvdata->amp_codec_id != MAX98360A)
435 		return -EINVAL;
436 
437 	return snd_soc_dapm_add_routes(&rtd->card->dapm, max98360a_map,
438 				       ARRAY_SIZE(max98360a_map));
439 }
440 
441 static const struct snd_soc_ops acp_card_maxim_ops = {
442 	.startup = acp_card_amp_startup,
443 	.shutdown = acp_card_shutdown,
444 };
445 
446 /* Declare nau8825 codec components */
447 SND_SOC_DAILINK_DEF(nau8825,
448 		    DAILINK_COMP_ARRAY(COMP_CODEC("i2c-10508825:00", "nau8825-hifi")));
449 
450 static const struct snd_soc_dapm_route nau8825_map[] = {
451 	{ "Headphone Jack", NULL, "HPOL" },
452 	{ "Headphone Jack", NULL, "HPOR" },
453 };
454 
455 static int acp_card_nau8825_init(struct snd_soc_pcm_runtime *rtd)
456 {
457 	struct snd_soc_card *card = rtd->card;
458 	struct acp_card_drvdata *drvdata = card->drvdata;
459 	struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
460 	struct snd_soc_component *component = codec_dai->component;
461 	unsigned int fmt;
462 	int ret;
463 
464 	dev_info(rtd->dev, "codec dai name = %s\n", codec_dai->name);
465 
466 	if (drvdata->hs_codec_id != NAU8825)
467 		return -EINVAL;
468 
469 	if (drvdata->soc_mclk)
470 		fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBC_CFC;
471 	else
472 		fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBP_CFP;
473 
474 	ret =  snd_soc_dai_set_fmt(codec_dai, fmt);
475 	if (ret < 0) {
476 		dev_err(rtd->card->dev, "Failed to set dai fmt: %d\n", ret);
477 		return ret;
478 	}
479 	ret = snd_soc_card_jack_new(card, "Headset Jack",
480 					 SND_JACK_HEADSET | SND_JACK_LINEOUT |
481 					 SND_JACK_BTN_0 | SND_JACK_BTN_1 |
482 					 SND_JACK_BTN_2 | SND_JACK_BTN_3,
483 					 &pco_jack);
484 	if (ret) {
485 		dev_err(card->dev, "HP jack creation failed %d\n", ret);
486 		return ret;
487 	}
488 
489 	snd_jack_set_key(pco_jack.jack, SND_JACK_BTN_0, KEY_PLAYPAUSE);
490 	snd_jack_set_key(pco_jack.jack, SND_JACK_BTN_1, KEY_VOICECOMMAND);
491 	snd_jack_set_key(pco_jack.jack, SND_JACK_BTN_2, KEY_VOLUMEUP);
492 	snd_jack_set_key(pco_jack.jack, SND_JACK_BTN_3, KEY_VOLUMEDOWN);
493 
494 	ret = snd_soc_component_set_jack(component, &pco_jack, NULL);
495 	if (ret) {
496 		dev_err(rtd->dev, "Headset Jack call-back failed: %d\n", ret);
497 		return ret;
498 	}
499 
500 	return snd_soc_dapm_add_routes(&rtd->card->dapm, nau8825_map, ARRAY_SIZE(nau8825_map));
501 }
502 
503 static int acp_nau8825_hw_params(struct snd_pcm_substream *substream,
504 				 struct snd_pcm_hw_params *params)
505 {
506 	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
507 	struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
508 	int ret;
509 
510 	ret = snd_soc_dai_set_sysclk(codec_dai, NAU8825_CLK_FLL_FS,
511 				     (48000 * 256), SND_SOC_CLOCK_IN);
512 	if (ret < 0)
513 		dev_err(rtd->dev, "snd_soc_dai_set_sysclk err = %d\n", ret);
514 
515 	ret = snd_soc_dai_set_pll(codec_dai, 0, 0, params_rate(params),
516 				  params_rate(params) * 256);
517 	if (ret < 0) {
518 		dev_err(rtd->dev, "can't set FLL: %d\n", ret);
519 		return ret;
520 	}
521 
522 	return ret;
523 }
524 
525 static int acp_nau8825_startup(struct snd_pcm_substream *substream)
526 {
527 	struct snd_pcm_runtime *runtime = substream->runtime;
528 
529 	runtime->hw.channels_max = 2;
530 	snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
531 				   &constraints_channels);
532 
533 	runtime->hw.formats = SNDRV_PCM_FMTBIT_S16_LE;
534 	snd_pcm_hw_constraint_list(runtime, 0,
535 				   SNDRV_PCM_HW_PARAM_RATE, &constraints_rates);
536 	return 0;
537 }
538 
539 static const struct snd_soc_ops acp_card_nau8825_ops = {
540 	.startup =  acp_nau8825_startup,
541 	.hw_params = acp_nau8825_hw_params,
542 };
543 
544 /* Declare DMIC codec components */
545 SND_SOC_DAILINK_DEF(dmic_codec,
546 		DAILINK_COMP_ARRAY(COMP_CODEC("dmic-codec", "dmic-hifi")));
547 
548 /* Declare ACP CPU components */
549 static struct snd_soc_dai_link_component dummy_codec[] = {
550 	{
551 		.name = "snd-soc-dummy",
552 		.dai_name = "snd-soc-dummy-dai",
553 	}
554 };
555 
556 static struct snd_soc_dai_link_component platform_component[] = {
557 	{
558 		 .name = "acp_asoc_renoir.0",
559 	}
560 };
561 
562 static struct snd_soc_dai_link_component sof_component[] = {
563 	{
564 		 .name = "0000:04:00.5",
565 	}
566 };
567 
568 SND_SOC_DAILINK_DEF(i2s_sp,
569 	DAILINK_COMP_ARRAY(COMP_CPU("acp-i2s-sp")));
570 SND_SOC_DAILINK_DEF(sof_sp,
571 	DAILINK_COMP_ARRAY(COMP_CPU("acp-sof-sp")));
572 SND_SOC_DAILINK_DEF(sof_hs,
573 		    DAILINK_COMP_ARRAY(COMP_CPU("acp-sof-hs")));
574 SND_SOC_DAILINK_DEF(sof_dmic,
575 	DAILINK_COMP_ARRAY(COMP_CPU("acp-sof-dmic")));
576 SND_SOC_DAILINK_DEF(pdm_dmic,
577 	DAILINK_COMP_ARRAY(COMP_CPU("acp-pdm-dmic")));
578 
579 int acp_sofdsp_dai_links_create(struct snd_soc_card *card)
580 {
581 	struct snd_soc_dai_link *links;
582 	struct device *dev = card->dev;
583 	struct acp_card_drvdata *drv_data = card->drvdata;
584 	int i = 0, num_links = 0;
585 
586 	if (drv_data->hs_cpu_id)
587 		num_links++;
588 	if (drv_data->amp_cpu_id)
589 		num_links++;
590 	if (drv_data->dmic_cpu_id)
591 		num_links++;
592 
593 	links = devm_kzalloc(dev, sizeof(struct snd_soc_dai_link) * num_links, GFP_KERNEL);
594 	if (!links)
595 		return -ENOMEM;
596 
597 	if (drv_data->hs_cpu_id == I2S_SP) {
598 		links[i].name = "acp-headset-codec";
599 		links[i].id = HEADSET_BE_ID;
600 		links[i].cpus = sof_sp;
601 		links[i].num_cpus = ARRAY_SIZE(sof_sp);
602 		links[i].platforms = sof_component;
603 		links[i].num_platforms = ARRAY_SIZE(sof_component);
604 		links[i].dpcm_playback = 1;
605 		links[i].dpcm_capture = 1;
606 		links[i].nonatomic = true;
607 		links[i].no_pcm = 1;
608 		if (!drv_data->hs_codec_id) {
609 			/* Use dummy codec if codec id not specified */
610 			links[i].codecs = dummy_codec;
611 			links[i].num_codecs = ARRAY_SIZE(dummy_codec);
612 		}
613 		if (drv_data->hs_codec_id == RT5682) {
614 			links[i].codecs = rt5682;
615 			links[i].num_codecs = ARRAY_SIZE(rt5682);
616 			links[i].init = acp_card_rt5682_init;
617 			links[i].ops = &acp_card_rt5682_ops;
618 		}
619 		if (drv_data->hs_codec_id == RT5682S) {
620 			links[i].codecs = rt5682s;
621 			links[i].num_codecs = ARRAY_SIZE(rt5682s);
622 			links[i].init = acp_card_rt5682s_init;
623 			links[i].ops = &acp_card_rt5682s_ops;
624 		}
625 		i++;
626 	}
627 
628 	if (drv_data->hs_cpu_id == I2S_HS) {
629 		links[i].name = "acp-headset-codec";
630 		links[i].id = HEADSET_BE_ID;
631 		links[i].cpus = sof_hs;
632 		links[i].num_cpus = ARRAY_SIZE(sof_hs);
633 		links[i].platforms = sof_component;
634 		links[i].num_platforms = ARRAY_SIZE(sof_component);
635 		links[i].dpcm_playback = 1;
636 		links[i].dpcm_capture = 1;
637 		links[i].nonatomic = true;
638 		links[i].no_pcm = 1;
639 		if (!drv_data->hs_codec_id) {
640 			/* Use dummy codec if codec id not specified */
641 			links[i].codecs = dummy_codec;
642 			links[i].num_codecs = ARRAY_SIZE(dummy_codec);
643 		}
644 		if (drv_data->hs_codec_id == NAU8825) {
645 			links[i].codecs = nau8825;
646 			links[i].num_codecs = ARRAY_SIZE(nau8825);
647 			links[i].init = acp_card_nau8825_init;
648 			links[i].ops = &acp_card_nau8825_ops;
649 		}
650 		if (drv_data->hs_codec_id == RT5682S) {
651 			links[i].codecs = rt5682s;
652 			links[i].num_codecs = ARRAY_SIZE(rt5682s);
653 			links[i].init = acp_card_rt5682s_init;
654 			links[i].ops = &acp_card_rt5682s_ops;
655 		}
656 		i++;
657 	}
658 
659 	if (drv_data->amp_cpu_id == I2S_SP) {
660 		links[i].name = "acp-amp-codec";
661 		links[i].id = AMP_BE_ID;
662 		links[i].cpus = sof_sp;
663 		links[i].num_cpus = ARRAY_SIZE(sof_sp);
664 		links[i].platforms = sof_component;
665 		links[i].num_platforms = ARRAY_SIZE(sof_component);
666 		links[i].dpcm_playback = 1;
667 		links[i].nonatomic = true;
668 		links[i].no_pcm = 1;
669 		if (!drv_data->amp_codec_id) {
670 			/* Use dummy codec if codec id not specified */
671 			links[i].codecs = dummy_codec;
672 			links[i].num_codecs = ARRAY_SIZE(dummy_codec);
673 		}
674 		if (drv_data->amp_codec_id == RT1019) {
675 			links[i].codecs = rt1019;
676 			links[i].num_codecs = ARRAY_SIZE(rt1019);
677 			links[i].ops = &acp_card_rt1019_ops;
678 			links[i].init = acp_card_rt1019_init;
679 			card->codec_conf = rt1019_conf;
680 			card->num_configs = ARRAY_SIZE(rt1019_conf);
681 		}
682 		if (drv_data->amp_codec_id == MAX98360A) {
683 			links[i].codecs = max98360a;
684 			links[i].num_codecs = ARRAY_SIZE(max98360a);
685 			links[i].ops = &acp_card_maxim_ops;
686 			links[i].init = acp_card_maxim_init;
687 		}
688 		i++;
689 	}
690 
691 	if (drv_data->amp_cpu_id == I2S_HS) {
692 		links[i].name = "acp-amp-codec";
693 		links[i].id = AMP_BE_ID;
694 		links[i].cpus = sof_hs;
695 		links[i].num_cpus = ARRAY_SIZE(sof_hs);
696 		links[i].platforms = sof_component;
697 		links[i].num_platforms = ARRAY_SIZE(sof_component);
698 		links[i].dpcm_playback = 1;
699 		links[i].nonatomic = true;
700 		links[i].no_pcm = 1;
701 		if (!drv_data->amp_codec_id) {
702 			/* Use dummy codec if codec id not specified */
703 			links[i].codecs = dummy_codec;
704 			links[i].num_codecs = ARRAY_SIZE(dummy_codec);
705 		}
706 		if (drv_data->amp_codec_id == MAX98360A) {
707 			links[i].codecs = max98360a;
708 			links[i].num_codecs = ARRAY_SIZE(max98360a);
709 			links[i].ops = &acp_card_maxim_ops;
710 			links[i].init = acp_card_maxim_init;
711 		}
712 		if (drv_data->amp_codec_id == RT1019) {
713 			links[i].codecs = rt1019;
714 			links[i].num_codecs = ARRAY_SIZE(rt1019);
715 			links[i].ops = &acp_card_rt1019_ops;
716 			links[i].init = acp_card_rt1019_init;
717 			card->codec_conf = rt1019_conf;
718 			card->num_configs = ARRAY_SIZE(rt1019_conf);
719 			links[i].codecs = rt1019_1;
720 			links[i].num_codecs = ARRAY_SIZE(rt1019_1);
721 			card->codec_conf = rt1019_1_conf;
722 			card->num_configs = ARRAY_SIZE(rt1019_1_conf);
723 		}
724 		i++;
725 	}
726 
727 	if (drv_data->dmic_cpu_id == DMIC) {
728 		links[i].name = "acp-dmic-codec";
729 		links[i].id = DMIC_BE_ID;
730 		links[i].codecs = dmic_codec;
731 		links[i].num_codecs = ARRAY_SIZE(dmic_codec);
732 		links[i].cpus = sof_dmic;
733 		links[i].num_cpus = ARRAY_SIZE(sof_dmic);
734 		links[i].platforms = sof_component;
735 		links[i].num_platforms = ARRAY_SIZE(sof_component);
736 		links[i].dpcm_capture = 1;
737 		links[i].nonatomic = true;
738 		links[i].no_pcm = 1;
739 	}
740 
741 	card->dai_link = links;
742 	card->num_links = num_links;
743 
744 	return 0;
745 }
746 EXPORT_SYMBOL_NS_GPL(acp_sofdsp_dai_links_create, SND_SOC_AMD_MACH);
747 
748 int acp_legacy_dai_links_create(struct snd_soc_card *card)
749 {
750 	struct snd_soc_dai_link *links;
751 	struct device *dev = card->dev;
752 	struct acp_card_drvdata *drv_data = card->drvdata;
753 	int i = 0, num_links = 0;
754 
755 	if (drv_data->hs_cpu_id)
756 		num_links++;
757 	if (drv_data->amp_cpu_id)
758 		num_links++;
759 	if (drv_data->dmic_cpu_id)
760 		num_links++;
761 
762 	links = devm_kzalloc(dev, sizeof(struct snd_soc_dai_link) * num_links, GFP_KERNEL);
763 	if (!links)
764 		return -ENOMEM;
765 
766 	if (drv_data->hs_cpu_id == I2S_SP) {
767 		links[i].name = "acp-headset-codec";
768 		links[i].id = HEADSET_BE_ID;
769 		links[i].cpus = i2s_sp;
770 		links[i].num_cpus = ARRAY_SIZE(i2s_sp);
771 		links[i].platforms = platform_component;
772 		links[i].num_platforms = ARRAY_SIZE(platform_component);
773 		links[i].dpcm_playback = 1;
774 		links[i].dpcm_capture = 1;
775 		if (!drv_data->hs_codec_id) {
776 			/* Use dummy codec if codec id not specified */
777 			links[i].codecs = dummy_codec;
778 			links[i].num_codecs = ARRAY_SIZE(dummy_codec);
779 		}
780 		if (drv_data->hs_codec_id == RT5682) {
781 			links[i].codecs = rt5682;
782 			links[i].num_codecs = ARRAY_SIZE(rt5682);
783 			links[i].init = acp_card_rt5682_init;
784 			links[i].ops = &acp_card_rt5682_ops;
785 		}
786 		if (drv_data->hs_codec_id == RT5682S) {
787 			links[i].codecs = rt5682s;
788 			links[i].num_codecs = ARRAY_SIZE(rt5682s);
789 			links[i].init = acp_card_rt5682s_init;
790 			links[i].ops = &acp_card_rt5682s_ops;
791 		}
792 		i++;
793 	}
794 
795 	if (drv_data->amp_cpu_id == I2S_SP) {
796 		links[i].name = "acp-amp-codec";
797 		links[i].id = AMP_BE_ID;
798 		links[i].cpus = i2s_sp;
799 		links[i].num_cpus = ARRAY_SIZE(i2s_sp);
800 		links[i].platforms = platform_component;
801 		links[i].num_platforms = ARRAY_SIZE(platform_component);
802 		links[i].dpcm_playback = 1;
803 		if (!drv_data->amp_codec_id) {
804 			/* Use dummy codec if codec id not specified */
805 			links[i].codecs = dummy_codec;
806 			links[i].num_codecs = ARRAY_SIZE(dummy_codec);
807 		}
808 		if (drv_data->amp_codec_id == RT1019) {
809 			links[i].codecs = rt1019;
810 			links[i].num_codecs = ARRAY_SIZE(rt1019);
811 			links[i].ops = &acp_card_rt1019_ops;
812 			links[i].init = acp_card_rt1019_init;
813 			card->codec_conf = rt1019_conf;
814 			card->num_configs = ARRAY_SIZE(rt1019_conf);
815 		}
816 		if (drv_data->amp_codec_id == MAX98360A) {
817 			links[i].codecs = max98360a;
818 			links[i].num_codecs = ARRAY_SIZE(max98360a);
819 			links[i].ops = &acp_card_maxim_ops;
820 			links[i].init = acp_card_maxim_init;
821 		}
822 		i++;
823 	}
824 
825 	if (drv_data->dmic_cpu_id == DMIC) {
826 		links[i].name = "acp-dmic-codec";
827 		links[i].id = DMIC_BE_ID;
828 		if (drv_data->dmic_codec_id == DMIC) {
829 			links[i].codecs = dmic_codec;
830 			links[i].num_codecs = ARRAY_SIZE(dmic_codec);
831 		} else {
832 			/* Use dummy codec if codec id not specified */
833 			links[i].codecs = dummy_codec;
834 			links[i].num_codecs = ARRAY_SIZE(dummy_codec);
835 		}
836 		links[i].cpus = pdm_dmic;
837 		links[i].num_cpus = ARRAY_SIZE(pdm_dmic);
838 		links[i].platforms = platform_component;
839 		links[i].num_platforms = ARRAY_SIZE(platform_component);
840 		links[i].ops = &acp_card_dmic_ops;
841 		links[i].dpcm_capture = 1;
842 	}
843 
844 	card->dai_link = links;
845 	card->num_links = num_links;
846 
847 	return 0;
848 }
849 EXPORT_SYMBOL_NS_GPL(acp_legacy_dai_links_create, SND_SOC_AMD_MACH);
850 
851 MODULE_LICENSE("GPL v2");
852