• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
acp_clk_enable(struct acp_card_drvdata * drvdata)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 */
acp_card_rt5682_init(struct snd_soc_pcm_runtime * rtd)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 
acp_card_hs_startup(struct snd_pcm_substream * substream)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 
acp_card_shutdown(struct snd_pcm_substream * substream)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 
acp_card_rt5682s_init(struct snd_soc_pcm_runtime * rtd)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 
acp_card_dmic_startup(struct snd_pcm_substream * substream)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 
317 static const struct snd_soc_dapm_route rt1019_map_lr[] = {
318 	{ "Left Spk", NULL, "Left SPO" },
319 	{ "Right Spk", NULL, "Right SPO" },
320 };
321 
322 static struct snd_soc_codec_conf rt1019_conf[] = {
323 	{
324 		 .dlc = COMP_CODEC_CONF("i2c-10EC1019:01"),
325 		 .name_prefix = "Left",
326 	},
327 	{
328 		 .dlc = COMP_CODEC_CONF("i2c-10EC1019:00"),
329 		 .name_prefix = "Right",
330 	},
331 };
332 
acp_card_rt1019_init(struct snd_soc_pcm_runtime * rtd)333 static int acp_card_rt1019_init(struct snd_soc_pcm_runtime *rtd)
334 {
335 	struct snd_soc_card *card = rtd->card;
336 	struct acp_card_drvdata *drvdata = card->drvdata;
337 
338 	if (drvdata->amp_codec_id != RT1019)
339 		return -EINVAL;
340 
341 	return snd_soc_dapm_add_routes(&rtd->card->dapm, rt1019_map_lr,
342 				       ARRAY_SIZE(rt1019_map_lr));
343 }
344 
acp_card_rt1019_hw_params(struct snd_pcm_substream * substream,struct snd_pcm_hw_params * params)345 static int acp_card_rt1019_hw_params(struct snd_pcm_substream *substream,
346 				     struct snd_pcm_hw_params *params)
347 {
348 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
349 	struct snd_soc_card *card = rtd->card;
350 	struct acp_card_drvdata *drvdata = card->drvdata;
351 	struct snd_soc_dai *codec_dai;
352 	int srate, i, ret = 0;
353 
354 	srate = params_rate(params);
355 
356 	if (drvdata->amp_codec_id != RT1019)
357 		return -EINVAL;
358 
359 	for_each_rtd_codec_dais(rtd, i, codec_dai) {
360 		if (strcmp(codec_dai->name, "rt1019-aif"))
361 			continue;
362 
363 		ret = snd_soc_dai_set_pll(codec_dai, 0, RT1019_PLL_S_BCLK,
364 					  64 * srate, 256 * srate);
365 		if (ret < 0)
366 			return ret;
367 
368 		ret = snd_soc_dai_set_sysclk(codec_dai, RT1019_SCLK_S_PLL,
369 					     256 * srate, SND_SOC_CLOCK_IN);
370 		if (ret < 0)
371 			return ret;
372 	}
373 
374 	return 0;
375 }
376 
acp_card_amp_startup(struct snd_pcm_substream * substream)377 static int acp_card_amp_startup(struct snd_pcm_substream *substream)
378 {
379 	struct snd_pcm_runtime *runtime = substream->runtime;
380 	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
381 	struct snd_soc_card *card = rtd->card;
382 	struct acp_card_drvdata *drvdata = card->drvdata;
383 	int ret = 0;
384 
385 	runtime->hw.channels_max = DUAL_CHANNEL;
386 	snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
387 				      &constraints_channels);
388 	snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
389 				      &constraints_rates);
390 
391 	if (!drvdata->soc_mclk) {
392 		ret = acp_clk_enable(drvdata);
393 		if (ret < 0) {
394 			dev_err(rtd->card->dev, "Failed to enable AMP clk: %d\n", ret);
395 			return ret;
396 		}
397 	}
398 	return ret;
399 }
400 
401 static const struct snd_soc_ops acp_card_rt1019_ops = {
402 	.startup = acp_card_amp_startup,
403 	.shutdown = acp_card_shutdown,
404 	.hw_params = acp_card_rt1019_hw_params,
405 };
406 
407 /* Declare Maxim codec components */
408 SND_SOC_DAILINK_DEF(max98360a,
409 	DAILINK_COMP_ARRAY(COMP_CODEC("MX98360A:00", "HiFi")));
410 
411 static const struct snd_soc_dapm_route max98360a_map[] = {
412 	{"Spk", NULL, "Speaker"},
413 };
414 
acp_card_maxim_init(struct snd_soc_pcm_runtime * rtd)415 static int acp_card_maxim_init(struct snd_soc_pcm_runtime *rtd)
416 {
417 	struct snd_soc_card *card = rtd->card;
418 	struct acp_card_drvdata *drvdata = card->drvdata;
419 
420 	if (drvdata->amp_codec_id != MAX98360A)
421 		return -EINVAL;
422 
423 	return snd_soc_dapm_add_routes(&rtd->card->dapm, max98360a_map,
424 				       ARRAY_SIZE(max98360a_map));
425 }
426 
427 static const struct snd_soc_ops acp_card_maxim_ops = {
428 	.startup = acp_card_amp_startup,
429 	.shutdown = acp_card_shutdown,
430 };
431 
432 /* Declare nau8825 codec components */
433 SND_SOC_DAILINK_DEF(nau8825,
434 		    DAILINK_COMP_ARRAY(COMP_CODEC("i2c-10508825:00", "nau8825-hifi")));
435 
436 static const struct snd_soc_dapm_route nau8825_map[] = {
437 	{ "Headphone Jack", NULL, "HPOL" },
438 	{ "Headphone Jack", NULL, "HPOR" },
439 };
440 
acp_card_nau8825_init(struct snd_soc_pcm_runtime * rtd)441 static int acp_card_nau8825_init(struct snd_soc_pcm_runtime *rtd)
442 {
443 	struct snd_soc_card *card = rtd->card;
444 	struct acp_card_drvdata *drvdata = card->drvdata;
445 	struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
446 	struct snd_soc_component *component = codec_dai->component;
447 	unsigned int fmt;
448 	int ret;
449 
450 	dev_info(rtd->dev, "codec dai name = %s\n", codec_dai->name);
451 
452 	if (drvdata->hs_codec_id != NAU8825)
453 		return -EINVAL;
454 
455 	if (drvdata->soc_mclk)
456 		fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBC_CFC;
457 	else
458 		fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBP_CFP;
459 
460 	ret =  snd_soc_dai_set_fmt(codec_dai, fmt);
461 	if (ret < 0) {
462 		dev_err(rtd->card->dev, "Failed to set dai fmt: %d\n", ret);
463 		return ret;
464 	}
465 	ret = snd_soc_card_jack_new(card, "Headset Jack",
466 					 SND_JACK_HEADSET | SND_JACK_LINEOUT |
467 					 SND_JACK_BTN_0 | SND_JACK_BTN_1 |
468 					 SND_JACK_BTN_2 | SND_JACK_BTN_3,
469 					 &pco_jack);
470 	if (ret) {
471 		dev_err(card->dev, "HP jack creation failed %d\n", ret);
472 		return ret;
473 	}
474 
475 	snd_jack_set_key(pco_jack.jack, SND_JACK_BTN_0, KEY_PLAYPAUSE);
476 	snd_jack_set_key(pco_jack.jack, SND_JACK_BTN_1, KEY_VOICECOMMAND);
477 	snd_jack_set_key(pco_jack.jack, SND_JACK_BTN_2, KEY_VOLUMEUP);
478 	snd_jack_set_key(pco_jack.jack, SND_JACK_BTN_3, KEY_VOLUMEDOWN);
479 
480 	ret = snd_soc_component_set_jack(component, &pco_jack, NULL);
481 	if (ret) {
482 		dev_err(rtd->dev, "Headset Jack call-back failed: %d\n", ret);
483 		return ret;
484 	}
485 
486 	return snd_soc_dapm_add_routes(&rtd->card->dapm, nau8825_map, ARRAY_SIZE(nau8825_map));
487 }
488 
acp_nau8825_hw_params(struct snd_pcm_substream * substream,struct snd_pcm_hw_params * params)489 static int acp_nau8825_hw_params(struct snd_pcm_substream *substream,
490 				 struct snd_pcm_hw_params *params)
491 {
492 	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
493 	struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
494 	int ret;
495 
496 	ret = snd_soc_dai_set_sysclk(codec_dai, NAU8825_CLK_FLL_FS,
497 				     (48000 * 256), SND_SOC_CLOCK_IN);
498 	if (ret < 0)
499 		dev_err(rtd->dev, "snd_soc_dai_set_sysclk err = %d\n", ret);
500 
501 	ret = snd_soc_dai_set_pll(codec_dai, 0, 0, params_rate(params),
502 				  params_rate(params) * 256);
503 	if (ret < 0) {
504 		dev_err(rtd->dev, "can't set FLL: %d\n", ret);
505 		return ret;
506 	}
507 
508 	return ret;
509 }
510 
acp_nau8825_startup(struct snd_pcm_substream * substream)511 static int acp_nau8825_startup(struct snd_pcm_substream *substream)
512 {
513 	struct snd_pcm_runtime *runtime = substream->runtime;
514 
515 	runtime->hw.channels_max = 2;
516 	snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
517 				   &constraints_channels);
518 
519 	runtime->hw.formats = SNDRV_PCM_FMTBIT_S16_LE;
520 	snd_pcm_hw_constraint_list(runtime, 0,
521 				   SNDRV_PCM_HW_PARAM_RATE, &constraints_rates);
522 	return 0;
523 }
524 
525 static const struct snd_soc_ops acp_card_nau8825_ops = {
526 	.startup =  acp_nau8825_startup,
527 	.hw_params = acp_nau8825_hw_params,
528 };
529 
530 /* Declare DMIC codec components */
531 SND_SOC_DAILINK_DEF(dmic_codec,
532 		DAILINK_COMP_ARRAY(COMP_CODEC("dmic-codec", "dmic-hifi")));
533 
534 /* Declare ACP CPU components */
535 static struct snd_soc_dai_link_component dummy_codec[] = {
536 	{
537 		.name = "snd-soc-dummy",
538 		.dai_name = "snd-soc-dummy-dai",
539 	}
540 };
541 
542 static struct snd_soc_dai_link_component platform_component[] = {
543 	{
544 		 .name = "acp_asoc_renoir.0",
545 	}
546 };
547 
548 static struct snd_soc_dai_link_component platform_rmb_component[] = {
549 	{
550 		.name = "acp_asoc_rembrandt.0",
551 	}
552 };
553 
554 static struct snd_soc_dai_link_component sof_component[] = {
555 	{
556 		 .name = "0000:04:00.5",
557 	}
558 };
559 
560 SND_SOC_DAILINK_DEF(i2s_sp,
561 	DAILINK_COMP_ARRAY(COMP_CPU("acp-i2s-sp")));
562 SND_SOC_DAILINK_DEF(i2s_hs,
563 		    DAILINK_COMP_ARRAY(COMP_CPU("acp-i2s-hs")));
564 SND_SOC_DAILINK_DEF(sof_sp,
565 	DAILINK_COMP_ARRAY(COMP_CPU("acp-sof-sp")));
566 SND_SOC_DAILINK_DEF(sof_hs,
567 		    DAILINK_COMP_ARRAY(COMP_CPU("acp-sof-hs")));
568 SND_SOC_DAILINK_DEF(sof_dmic,
569 	DAILINK_COMP_ARRAY(COMP_CPU("acp-sof-dmic")));
570 SND_SOC_DAILINK_DEF(pdm_dmic,
571 	DAILINK_COMP_ARRAY(COMP_CPU("acp-pdm-dmic")));
572 
acp_sofdsp_dai_links_create(struct snd_soc_card * card)573 int acp_sofdsp_dai_links_create(struct snd_soc_card *card)
574 {
575 	struct snd_soc_dai_link *links;
576 	struct device *dev = card->dev;
577 	struct acp_card_drvdata *drv_data = card->drvdata;
578 	int i = 0, num_links = 0;
579 
580 	if (drv_data->hs_cpu_id)
581 		num_links++;
582 	if (drv_data->amp_cpu_id)
583 		num_links++;
584 	if (drv_data->dmic_cpu_id)
585 		num_links++;
586 
587 	links = devm_kcalloc(dev, num_links, sizeof(struct snd_soc_dai_link), GFP_KERNEL);
588 	if (!links)
589 		return -ENOMEM;
590 
591 	if (drv_data->hs_cpu_id == I2S_SP) {
592 		links[i].name = "acp-headset-codec";
593 		links[i].id = HEADSET_BE_ID;
594 		links[i].cpus = sof_sp;
595 		links[i].num_cpus = ARRAY_SIZE(sof_sp);
596 		links[i].platforms = sof_component;
597 		links[i].num_platforms = ARRAY_SIZE(sof_component);
598 		links[i].dpcm_playback = 1;
599 		links[i].dpcm_capture = 1;
600 		links[i].nonatomic = true;
601 		links[i].no_pcm = 1;
602 		if (!drv_data->hs_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->hs_codec_id == RT5682) {
608 			links[i].codecs = rt5682;
609 			links[i].num_codecs = ARRAY_SIZE(rt5682);
610 			links[i].init = acp_card_rt5682_init;
611 			links[i].ops = &acp_card_rt5682_ops;
612 		}
613 		if (drv_data->hs_codec_id == RT5682S) {
614 			links[i].codecs = rt5682s;
615 			links[i].num_codecs = ARRAY_SIZE(rt5682s);
616 			links[i].init = acp_card_rt5682s_init;
617 			links[i].ops = &acp_card_rt5682s_ops;
618 		}
619 		i++;
620 	}
621 
622 	if (drv_data->hs_cpu_id == I2S_HS) {
623 		links[i].name = "acp-headset-codec";
624 		links[i].id = HEADSET_BE_ID;
625 		links[i].cpus = sof_hs;
626 		links[i].num_cpus = ARRAY_SIZE(sof_hs);
627 		links[i].platforms = sof_component;
628 		links[i].num_platforms = ARRAY_SIZE(sof_component);
629 		links[i].dpcm_playback = 1;
630 		links[i].dpcm_capture = 1;
631 		links[i].nonatomic = true;
632 		links[i].no_pcm = 1;
633 		if (!drv_data->hs_codec_id) {
634 			/* Use dummy codec if codec id not specified */
635 			links[i].codecs = dummy_codec;
636 			links[i].num_codecs = ARRAY_SIZE(dummy_codec);
637 		}
638 		if (drv_data->hs_codec_id == NAU8825) {
639 			links[i].codecs = nau8825;
640 			links[i].num_codecs = ARRAY_SIZE(nau8825);
641 			links[i].init = acp_card_nau8825_init;
642 			links[i].ops = &acp_card_nau8825_ops;
643 		}
644 		if (drv_data->hs_codec_id == RT5682S) {
645 			links[i].codecs = rt5682s;
646 			links[i].num_codecs = ARRAY_SIZE(rt5682s);
647 			links[i].init = acp_card_rt5682s_init;
648 			links[i].ops = &acp_card_rt5682s_ops;
649 		}
650 		i++;
651 	}
652 
653 	if (drv_data->amp_cpu_id == I2S_SP) {
654 		links[i].name = "acp-amp-codec";
655 		links[i].id = AMP_BE_ID;
656 		links[i].cpus = sof_sp;
657 		links[i].num_cpus = ARRAY_SIZE(sof_sp);
658 		links[i].platforms = sof_component;
659 		links[i].num_platforms = ARRAY_SIZE(sof_component);
660 		links[i].dpcm_playback = 1;
661 		links[i].nonatomic = true;
662 		links[i].no_pcm = 1;
663 		if (!drv_data->amp_codec_id) {
664 			/* Use dummy codec if codec id not specified */
665 			links[i].codecs = dummy_codec;
666 			links[i].num_codecs = ARRAY_SIZE(dummy_codec);
667 		}
668 		if (drv_data->amp_codec_id == RT1019) {
669 			links[i].codecs = rt1019;
670 			links[i].num_codecs = ARRAY_SIZE(rt1019);
671 			links[i].ops = &acp_card_rt1019_ops;
672 			links[i].init = acp_card_rt1019_init;
673 			card->codec_conf = rt1019_conf;
674 			card->num_configs = ARRAY_SIZE(rt1019_conf);
675 		}
676 		if (drv_data->amp_codec_id == MAX98360A) {
677 			links[i].codecs = max98360a;
678 			links[i].num_codecs = ARRAY_SIZE(max98360a);
679 			links[i].ops = &acp_card_maxim_ops;
680 			links[i].init = acp_card_maxim_init;
681 		}
682 		i++;
683 	}
684 
685 	if (drv_data->amp_cpu_id == I2S_HS) {
686 		links[i].name = "acp-amp-codec";
687 		links[i].id = AMP_BE_ID;
688 		links[i].cpus = sof_hs;
689 		links[i].num_cpus = ARRAY_SIZE(sof_hs);
690 		links[i].platforms = sof_component;
691 		links[i].num_platforms = ARRAY_SIZE(sof_component);
692 		links[i].dpcm_playback = 1;
693 		links[i].nonatomic = true;
694 		links[i].no_pcm = 1;
695 		if (!drv_data->amp_codec_id) {
696 			/* Use dummy codec if codec id not specified */
697 			links[i].codecs = dummy_codec;
698 			links[i].num_codecs = ARRAY_SIZE(dummy_codec);
699 		}
700 		if (drv_data->amp_codec_id == MAX98360A) {
701 			links[i].codecs = max98360a;
702 			links[i].num_codecs = ARRAY_SIZE(max98360a);
703 			links[i].ops = &acp_card_maxim_ops;
704 			links[i].init = acp_card_maxim_init;
705 		}
706 		if (drv_data->amp_codec_id == RT1019) {
707 			links[i].codecs = rt1019;
708 			links[i].num_codecs = ARRAY_SIZE(rt1019);
709 			links[i].ops = &acp_card_rt1019_ops;
710 			links[i].init = acp_card_rt1019_init;
711 			card->codec_conf = rt1019_conf;
712 			card->num_configs = ARRAY_SIZE(rt1019_conf);
713 		}
714 		i++;
715 	}
716 
717 	if (drv_data->dmic_cpu_id == DMIC) {
718 		links[i].name = "acp-dmic-codec";
719 		links[i].id = DMIC_BE_ID;
720 		links[i].codecs = dmic_codec;
721 		links[i].num_codecs = ARRAY_SIZE(dmic_codec);
722 		links[i].cpus = sof_dmic;
723 		links[i].num_cpus = ARRAY_SIZE(sof_dmic);
724 		links[i].platforms = sof_component;
725 		links[i].num_platforms = ARRAY_SIZE(sof_component);
726 		links[i].dpcm_capture = 1;
727 		links[i].nonatomic = true;
728 		links[i].no_pcm = 1;
729 	}
730 
731 	card->dai_link = links;
732 	card->num_links = num_links;
733 
734 	return 0;
735 }
736 EXPORT_SYMBOL_NS_GPL(acp_sofdsp_dai_links_create, SND_SOC_AMD_MACH);
737 
acp_legacy_dai_links_create(struct snd_soc_card * card)738 int acp_legacy_dai_links_create(struct snd_soc_card *card)
739 {
740 	struct snd_soc_dai_link *links;
741 	struct device *dev = card->dev;
742 	struct acp_card_drvdata *drv_data = card->drvdata;
743 	int i = 0, num_links = 0;
744 
745 	if (drv_data->hs_cpu_id)
746 		num_links++;
747 	if (drv_data->amp_cpu_id)
748 		num_links++;
749 	if (drv_data->dmic_cpu_id)
750 		num_links++;
751 
752 	links = devm_kcalloc(dev, num_links, sizeof(struct snd_soc_dai_link), GFP_KERNEL);
753 	if (!links)
754 		return -ENOMEM;
755 
756 	if (drv_data->hs_cpu_id == I2S_SP) {
757 		links[i].name = "acp-headset-codec";
758 		links[i].id = HEADSET_BE_ID;
759 		links[i].cpus = i2s_sp;
760 		links[i].num_cpus = ARRAY_SIZE(i2s_sp);
761 		links[i].platforms = platform_component;
762 		links[i].num_platforms = ARRAY_SIZE(platform_component);
763 		links[i].dpcm_playback = 1;
764 		links[i].dpcm_capture = 1;
765 		if (!drv_data->hs_codec_id) {
766 			/* Use dummy codec if codec id not specified */
767 			links[i].codecs = dummy_codec;
768 			links[i].num_codecs = ARRAY_SIZE(dummy_codec);
769 		}
770 		if (drv_data->hs_codec_id == RT5682) {
771 			links[i].codecs = rt5682;
772 			links[i].num_codecs = ARRAY_SIZE(rt5682);
773 			links[i].init = acp_card_rt5682_init;
774 			links[i].ops = &acp_card_rt5682_ops;
775 		}
776 		if (drv_data->hs_codec_id == RT5682S) {
777 			links[i].codecs = rt5682s;
778 			links[i].num_codecs = ARRAY_SIZE(rt5682s);
779 			links[i].init = acp_card_rt5682s_init;
780 			links[i].ops = &acp_card_rt5682s_ops;
781 		}
782 		i++;
783 	}
784 
785 	if (drv_data->hs_cpu_id == I2S_HS) {
786 		links[i].name = "acp-headset-codec";
787 		links[i].id = HEADSET_BE_ID;
788 		links[i].cpus = i2s_hs;
789 		links[i].num_cpus = ARRAY_SIZE(i2s_hs);
790 		if (drv_data->platform == REMBRANDT) {
791 			links[i].platforms = platform_rmb_component;
792 			links[i].num_platforms = ARRAY_SIZE(platform_rmb_component);
793 		} else {
794 			links[i].platforms = platform_component;
795 			links[i].num_platforms = ARRAY_SIZE(platform_component);
796 		}
797 		links[i].dpcm_playback = 1;
798 		links[i].dpcm_capture = 1;
799 		if (!drv_data->hs_codec_id) {
800 			/* Use dummy codec if codec id not specified */
801 			links[i].codecs = dummy_codec;
802 			links[i].num_codecs = ARRAY_SIZE(dummy_codec);
803 		}
804 		if (drv_data->hs_codec_id == NAU8825) {
805 			links[i].codecs = nau8825;
806 			links[i].num_codecs = ARRAY_SIZE(nau8825);
807 			links[i].init = acp_card_nau8825_init;
808 			links[i].ops = &acp_card_nau8825_ops;
809 		}
810 		if (drv_data->hs_codec_id == RT5682S) {
811 			links[i].codecs = rt5682s;
812 			links[i].num_codecs = ARRAY_SIZE(rt5682s);
813 			links[i].init = acp_card_rt5682s_init;
814 			links[i].ops = &acp_card_rt5682s_ops;
815 		}
816 		i++;
817 	}
818 
819 	if (drv_data->amp_cpu_id == I2S_SP) {
820 		links[i].name = "acp-amp-codec";
821 		links[i].id = AMP_BE_ID;
822 		links[i].cpus = i2s_sp;
823 		links[i].num_cpus = ARRAY_SIZE(i2s_sp);
824 		links[i].platforms = platform_component;
825 		links[i].num_platforms = ARRAY_SIZE(platform_component);
826 		links[i].dpcm_playback = 1;
827 		if (!drv_data->amp_codec_id) {
828 			/* Use dummy codec if codec id not specified */
829 			links[i].codecs = dummy_codec;
830 			links[i].num_codecs = ARRAY_SIZE(dummy_codec);
831 		}
832 		if (drv_data->amp_codec_id == RT1019) {
833 			links[i].codecs = rt1019;
834 			links[i].num_codecs = ARRAY_SIZE(rt1019);
835 			links[i].ops = &acp_card_rt1019_ops;
836 			links[i].init = acp_card_rt1019_init;
837 			card->codec_conf = rt1019_conf;
838 			card->num_configs = ARRAY_SIZE(rt1019_conf);
839 		}
840 		if (drv_data->amp_codec_id == MAX98360A) {
841 			links[i].codecs = max98360a;
842 			links[i].num_codecs = ARRAY_SIZE(max98360a);
843 			links[i].ops = &acp_card_maxim_ops;
844 			links[i].init = acp_card_maxim_init;
845 		}
846 		i++;
847 	}
848 
849 	if (drv_data->amp_cpu_id == I2S_HS) {
850 		links[i].name = "acp-amp-codec";
851 		links[i].id = AMP_BE_ID;
852 		links[i].cpus = i2s_hs;
853 		links[i].num_cpus = ARRAY_SIZE(i2s_hs);
854 		if (drv_data->platform == REMBRANDT) {
855 			links[i].platforms = platform_rmb_component;
856 			links[i].num_platforms = ARRAY_SIZE(platform_rmb_component);
857 		} else {
858 			links[i].platforms = platform_component;
859 			links[i].num_platforms = ARRAY_SIZE(platform_component);
860 		}
861 		links[i].dpcm_playback = 1;
862 		if (!drv_data->amp_codec_id) {
863 			/* Use dummy codec if codec id not specified */
864 			links[i].codecs = dummy_codec;
865 			links[i].num_codecs = ARRAY_SIZE(dummy_codec);
866 		}
867 		if (drv_data->amp_codec_id == MAX98360A) {
868 			links[i].codecs = max98360a;
869 			links[i].num_codecs = ARRAY_SIZE(max98360a);
870 			links[i].ops = &acp_card_maxim_ops;
871 			links[i].init = acp_card_maxim_init;
872 		}
873 		if (drv_data->amp_codec_id == RT1019) {
874 			links[i].codecs = rt1019;
875 			links[i].num_codecs = ARRAY_SIZE(rt1019);
876 			links[i].ops = &acp_card_rt1019_ops;
877 			links[i].init = acp_card_rt1019_init;
878 			card->codec_conf = rt1019_conf;
879 			card->num_configs = ARRAY_SIZE(rt1019_conf);
880 		}
881 		i++;
882 	}
883 
884 	if (drv_data->dmic_cpu_id == DMIC) {
885 		links[i].name = "acp-dmic-codec";
886 		links[i].id = DMIC_BE_ID;
887 		if (drv_data->dmic_codec_id == DMIC) {
888 			links[i].codecs = dmic_codec;
889 			links[i].num_codecs = ARRAY_SIZE(dmic_codec);
890 		} else {
891 			/* Use dummy codec if codec id not specified */
892 			links[i].codecs = dummy_codec;
893 			links[i].num_codecs = ARRAY_SIZE(dummy_codec);
894 		}
895 		links[i].cpus = pdm_dmic;
896 		links[i].num_cpus = ARRAY_SIZE(pdm_dmic);
897 		if (drv_data->platform == REMBRANDT) {
898 			links[i].platforms = platform_rmb_component;
899 			links[i].num_platforms = ARRAY_SIZE(platform_rmb_component);
900 		} else {
901 			links[i].platforms = platform_component;
902 			links[i].num_platforms = ARRAY_SIZE(platform_component);
903 		}
904 		links[i].ops = &acp_card_dmic_ops;
905 		links[i].dpcm_capture = 1;
906 	}
907 
908 	card->dai_link = links;
909 	card->num_links = num_links;
910 
911 	return 0;
912 }
913 EXPORT_SYMBOL_NS_GPL(acp_legacy_dai_links_create, SND_SOC_AMD_MACH);
914 
915 MODULE_LICENSE("GPL v2");
916