1 // SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause)
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.
6 // Copyright(c) 2021 Advanced Micro Devices, Inc.
8 // Authors: Ajit Kumar Pandey <AjitKumar.Pandey@amd.com>
9 // Vijendar Mukunda <Vijendar.Mukunda@amd.com>
13 * Machine Driver Interface for ACP HW block
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>
24 #include "../../codecs/rt5682.h"
25 #include "../../codecs/rt1019.h"
26 #include "../../codecs/rt5682s.h"
29 #define PCO_PLAT_CLK 48000000
30 #define RT5682_PLL_FREQ (48000 * 512)
31 #define DUAL_CHANNEL 2
32 #define FOUR_CHANNEL 4
34 static struct snd_soc_jack pco_jack;
36 static const unsigned int channels[] = {
40 static const unsigned int rates[] = {
44 static const struct snd_pcm_hw_constraint_list constraints_rates = {
45 .count = ARRAY_SIZE(rates),
50 static const struct snd_pcm_hw_constraint_list constraints_channels = {
51 .count = ARRAY_SIZE(channels),
56 static int acp_clk_enable(struct acp_card_drvdata *drvdata)
58 clk_set_rate(drvdata->wclk, 48000);
59 clk_set_rate(drvdata->bclk, 48000 * 64);
61 return clk_prepare_enable(drvdata->wclk);
64 /* Declare RT5682 codec components */
65 SND_SOC_DAILINK_DEF(rt5682,
66 DAILINK_COMP_ARRAY(COMP_CODEC("i2c-10EC5682:00", "rt5682-aif1")));
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" },
74 /* Define card ops for RT5682 CODEC */
75 static int acp_card_rt5682_init(struct snd_soc_pcm_runtime *rtd)
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;
83 dev_info(rtd->dev, "codec dai name = %s\n", codec_dai->name);
85 if (drvdata->hs_codec_id != RT5682)
88 ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
89 | SND_SOC_DAIFMT_CBP_CFP);
91 dev_err(rtd->card->dev, "Failed to set dai fmt: %d\n", ret);
95 ret = snd_soc_dai_set_pll(codec_dai, RT5682_PLL2, RT5682_PLL2_S_MCLK,
96 PCO_PLAT_CLK, RT5682_PLL_FREQ);
98 dev_err(rtd->dev, "Failed to set codec PLL: %d\n", ret);
102 ret = snd_soc_dai_set_sysclk(codec_dai, RT5682_SCLK_S_PLL2,
103 RT5682_PLL_FREQ, SND_SOC_CLOCK_IN);
105 dev_err(rtd->dev, "Failed to set codec SYSCLK: %d\n", ret);
109 /* Set tdm/i2s1 master bclk ratio */
110 ret = snd_soc_dai_set_bclk_ratio(codec_dai, 64);
112 dev_err(rtd->dev, "Failed to set rt5682 tdm bclk ratio: %d\n", ret);
116 drvdata->wclk = clk_get(component->dev, "rt5682-dai-wclk");
117 drvdata->bclk = clk_get(component->dev, "rt5682-dai-bclk");
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,
125 dev_err(card->dev, "HP jack creation failed %d\n", ret);
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);
134 ret = snd_soc_component_set_jack(component, &pco_jack, NULL);
136 dev_err(rtd->dev, "Headset Jack call-back failed: %d\n", ret);
140 return snd_soc_dapm_add_routes(&rtd->card->dapm, rt5682_map, ARRAY_SIZE(rt5682_map));
143 static int acp_card_hs_startup(struct snd_pcm_substream *substream)
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);
152 ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
153 | SND_SOC_DAIFMT_CBP_CFP);
155 dev_err(rtd->card->dev, "Failed to set dai fmt: %d\n", ret);
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,
165 ret = acp_clk_enable(drvdata);
167 dev_err(rtd->card->dev, "Failed to enable HS clk: %d\n", ret);
172 static void acp_card_shutdown(struct snd_pcm_substream *substream)
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;
178 clk_disable_unprepare(drvdata->wclk);
181 static const struct snd_soc_ops acp_card_rt5682_ops = {
182 .startup = acp_card_hs_startup,
183 .shutdown = acp_card_shutdown,
186 /* Define RT5682S CODEC component*/
187 SND_SOC_DAILINK_DEF(rt5682s,
188 DAILINK_COMP_ARRAY(COMP_CODEC("i2c-RTL5682:00", "rt5682s-aif1")));
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" },
196 static int acp_card_rt5682s_init(struct snd_soc_pcm_runtime *rtd)
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;
204 dev_info(rtd->dev, "codec dai name = %s\n", codec_dai->name);
206 if (drvdata->hs_codec_id != RT5682S)
209 ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
210 | SND_SOC_DAIFMT_CBP_CFP);
212 dev_err(rtd->card->dev, "Failed to set dai fmt: %d\n", ret);
216 ret = snd_soc_dai_set_pll(codec_dai, RT5682S_PLL2, RT5682S_PLL_S_MCLK,
217 PCO_PLAT_CLK, RT5682_PLL_FREQ);
219 dev_err(rtd->dev, "Failed to set codec PLL: %d\n", ret);
223 ret = snd_soc_dai_set_sysclk(codec_dai, RT5682S_SCLK_S_PLL2,
224 RT5682_PLL_FREQ, SND_SOC_CLOCK_IN);
226 dev_err(rtd->dev, "Failed to set codec SYSCLK: %d\n", ret);
230 /* Set tdm/i2s1 master bclk ratio */
231 ret = snd_soc_dai_set_bclk_ratio(codec_dai, 64);
233 dev_err(rtd->dev, "Failed to set rt5682 tdm bclk ratio: %d\n", ret);
237 drvdata->wclk = clk_get(component->dev, "rt5682-dai-wclk");
238 drvdata->bclk = clk_get(component->dev, "rt5682-dai-bclk");
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,
246 dev_err(card->dev, "HP jack creation failed %d\n", ret);
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);
255 ret = snd_soc_component_set_jack(component, &pco_jack, NULL);
257 dev_err(rtd->dev, "Headset Jack call-back failed: %d\n", ret);
261 return snd_soc_dapm_add_routes(&rtd->card->dapm, rt5682s_map, ARRAY_SIZE(rt5682s_map));
264 static const struct snd_soc_ops acp_card_rt5682s_ops = {
265 .startup = acp_card_hs_startup,
266 .shutdown = acp_card_shutdown,
269 static const unsigned int dmic_channels[] = {
270 DUAL_CHANNEL, FOUR_CHANNEL,
273 static const struct snd_pcm_hw_constraint_list dmic_constraints_channels = {
274 .count = ARRAY_SIZE(dmic_channels),
275 .list = dmic_channels,
279 static int acp_card_dmic_startup(struct snd_pcm_substream *substream)
281 struct snd_pcm_runtime *runtime = substream->runtime;
283 snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
284 &dmic_constraints_channels);
285 snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
291 static const struct snd_soc_ops acp_card_dmic_ops = {
292 .startup = acp_card_dmic_startup,
295 /* Declare RT1019 codec components */
296 SND_SOC_DAILINK_DEF(rt1019,
297 DAILINK_COMP_ARRAY(COMP_CODEC("i2c-10EC1019:00", "rt1019-aif"),
298 COMP_CODEC("i2c-10EC1019:01", "rt1019-aif")));
300 static const struct snd_soc_dapm_route rt1019_map_lr[] = {
301 { "Left Spk", NULL, "Left SPO" },
302 { "Right Spk", NULL, "Right SPO" },
305 static struct snd_soc_codec_conf rt1019_conf[] = {
307 .dlc = COMP_CODEC_CONF("i2c-10EC1019:01"),
308 .name_prefix = "Left",
311 .dlc = COMP_CODEC_CONF("i2c-10EC1019:00"),
312 .name_prefix = "Right",
316 static int acp_card_rt1019_init(struct snd_soc_pcm_runtime *rtd)
318 struct snd_soc_card *card = rtd->card;
319 struct acp_card_drvdata *drvdata = card->drvdata;
321 if (drvdata->amp_codec_id != RT1019)
324 return snd_soc_dapm_add_routes(&rtd->card->dapm, rt1019_map_lr,
325 ARRAY_SIZE(rt1019_map_lr));
328 static int acp_card_rt1019_hw_params(struct snd_pcm_substream *substream,
329 struct snd_pcm_hw_params *params)
331 struct snd_soc_pcm_runtime *rtd = substream->private_data;
332 struct snd_soc_card *card = rtd->card;
333 struct acp_card_drvdata *drvdata = card->drvdata;
334 struct snd_soc_dai *codec_dai;
335 int srate, i, ret = 0;
337 srate = params_rate(params);
339 if (drvdata->amp_codec_id != RT1019)
342 for_each_rtd_codec_dais(rtd, i, codec_dai) {
343 if (strcmp(codec_dai->name, "rt1019-aif"))
346 ret = snd_soc_dai_set_pll(codec_dai, 0, RT1019_PLL_S_BCLK,
347 64 * srate, 256 * srate);
351 ret = snd_soc_dai_set_sysclk(codec_dai, RT1019_SCLK_S_PLL,
352 256 * srate, SND_SOC_CLOCK_IN);
360 static int acp_card_amp_startup(struct snd_pcm_substream *substream)
362 struct snd_pcm_runtime *runtime = substream->runtime;
363 struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
364 struct snd_soc_card *card = rtd->card;
365 struct acp_card_drvdata *drvdata = card->drvdata;
368 runtime->hw.channels_max = DUAL_CHANNEL;
369 snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
370 &constraints_channels);
371 snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
374 ret = acp_clk_enable(drvdata);
376 dev_err(rtd->card->dev, "Failed to enable AMP clk: %d\n", ret);
381 static const struct snd_soc_ops acp_card_rt1019_ops = {
382 .startup = acp_card_amp_startup,
383 .shutdown = acp_card_shutdown,
384 .hw_params = acp_card_rt1019_hw_params,
387 /* Declare Maxim codec components */
388 SND_SOC_DAILINK_DEF(max98360a,
389 DAILINK_COMP_ARRAY(COMP_CODEC("MX98360A:00", "HiFi")));
391 static const struct snd_soc_dapm_route max98360a_map[] = {
392 {"Spk", NULL, "Speaker"},
395 static int acp_card_maxim_init(struct snd_soc_pcm_runtime *rtd)
397 struct snd_soc_card *card = rtd->card;
398 struct acp_card_drvdata *drvdata = card->drvdata;
400 if (drvdata->amp_codec_id != MAX98360A)
403 return snd_soc_dapm_add_routes(&rtd->card->dapm, max98360a_map,
404 ARRAY_SIZE(max98360a_map));
407 static const struct snd_soc_ops acp_card_maxim_ops = {
408 .startup = acp_card_amp_startup,
409 .shutdown = acp_card_shutdown,
412 /* Declare DMIC codec components */
413 SND_SOC_DAILINK_DEF(dmic_codec,
414 DAILINK_COMP_ARRAY(COMP_CODEC("dmic-codec", "dmic-hifi")));
416 /* Declare ACP CPU components */
417 static struct snd_soc_dai_link_component dummy_codec[] = {
419 .name = "snd-soc-dummy",
420 .dai_name = "snd-soc-dummy-dai",
424 static struct snd_soc_dai_link_component platform_component[] = {
426 .name = "acp_asoc_renoir.0",
430 static struct snd_soc_dai_link_component sof_component[] = {
432 .name = "0000:04:00.5",
436 SND_SOC_DAILINK_DEF(i2s_sp,
437 DAILINK_COMP_ARRAY(COMP_CPU("acp-i2s-sp")));
438 SND_SOC_DAILINK_DEF(sof_sp,
439 DAILINK_COMP_ARRAY(COMP_CPU("acp-sof-sp")));
440 SND_SOC_DAILINK_DEF(sof_dmic,
441 DAILINK_COMP_ARRAY(COMP_CPU("acp-sof-dmic")));
442 SND_SOC_DAILINK_DEF(pdm_dmic,
443 DAILINK_COMP_ARRAY(COMP_CPU("acp-pdm-dmic")));
445 int acp_sofdsp_dai_links_create(struct snd_soc_card *card)
447 struct snd_soc_dai_link *links;
448 struct device *dev = card->dev;
449 struct acp_card_drvdata *drv_data = card->drvdata;
450 int i = 0, num_links = 0;
452 if (drv_data->hs_cpu_id)
454 if (drv_data->amp_cpu_id)
456 if (drv_data->dmic_cpu_id)
459 links = devm_kzalloc(dev, sizeof(struct snd_soc_dai_link) * num_links, GFP_KERNEL);
463 if (drv_data->hs_cpu_id == I2S_SP) {
464 links[i].name = "acp-headset-codec";
465 links[i].id = HEADSET_BE_ID;
466 links[i].cpus = sof_sp;
467 links[i].num_cpus = ARRAY_SIZE(sof_sp);
468 links[i].platforms = sof_component;
469 links[i].num_platforms = ARRAY_SIZE(sof_component);
470 links[i].dpcm_playback = 1;
471 links[i].dpcm_capture = 1;
472 links[i].nonatomic = true;
474 if (!drv_data->hs_codec_id) {
475 /* Use dummy codec if codec id not specified */
476 links[i].codecs = dummy_codec;
477 links[i].num_codecs = ARRAY_SIZE(dummy_codec);
479 if (drv_data->hs_codec_id == RT5682) {
480 links[i].codecs = rt5682;
481 links[i].num_codecs = ARRAY_SIZE(rt5682);
482 links[i].init = acp_card_rt5682_init;
483 links[i].ops = &acp_card_rt5682_ops;
485 if (drv_data->hs_codec_id == RT5682S) {
486 links[i].codecs = rt5682s;
487 links[i].num_codecs = ARRAY_SIZE(rt5682s);
488 links[i].init = acp_card_rt5682s_init;
489 links[i].ops = &acp_card_rt5682s_ops;
494 if (drv_data->amp_cpu_id == I2S_SP) {
495 links[i].name = "acp-amp-codec";
496 links[i].id = AMP_BE_ID;
497 links[i].cpus = sof_sp;
498 links[i].num_cpus = ARRAY_SIZE(sof_sp);
499 links[i].platforms = sof_component;
500 links[i].num_platforms = ARRAY_SIZE(sof_component);
501 links[i].dpcm_playback = 1;
502 links[i].nonatomic = true;
504 if (!drv_data->amp_codec_id) {
505 /* Use dummy codec if codec id not specified */
506 links[i].codecs = dummy_codec;
507 links[i].num_codecs = ARRAY_SIZE(dummy_codec);
509 if (drv_data->amp_codec_id == RT1019) {
510 links[i].codecs = rt1019;
511 links[i].num_codecs = ARRAY_SIZE(rt1019);
512 links[i].ops = &acp_card_rt1019_ops;
513 links[i].init = acp_card_rt1019_init;
514 card->codec_conf = rt1019_conf;
515 card->num_configs = ARRAY_SIZE(rt1019_conf);
517 if (drv_data->amp_codec_id == MAX98360A) {
518 links[i].codecs = max98360a;
519 links[i].num_codecs = ARRAY_SIZE(max98360a);
520 links[i].ops = &acp_card_maxim_ops;
521 links[i].init = acp_card_maxim_init;
526 if (drv_data->dmic_cpu_id == DMIC) {
527 links[i].name = "acp-dmic-codec";
528 links[i].id = DMIC_BE_ID;
529 links[i].codecs = dmic_codec;
530 links[i].num_codecs = ARRAY_SIZE(dmic_codec);
531 links[i].cpus = sof_dmic;
532 links[i].num_cpus = ARRAY_SIZE(sof_dmic);
533 links[i].platforms = sof_component;
534 links[i].num_platforms = ARRAY_SIZE(sof_component);
535 links[i].dpcm_capture = 1;
536 links[i].nonatomic = true;
540 card->dai_link = links;
541 card->num_links = num_links;
545 EXPORT_SYMBOL_NS_GPL(acp_sofdsp_dai_links_create, SND_SOC_AMD_MACH);
547 int acp_legacy_dai_links_create(struct snd_soc_card *card)
549 struct snd_soc_dai_link *links;
550 struct device *dev = card->dev;
551 struct acp_card_drvdata *drv_data = card->drvdata;
552 int i = 0, num_links = 0;
554 if (drv_data->hs_cpu_id)
556 if (drv_data->amp_cpu_id)
558 if (drv_data->dmic_cpu_id)
561 links = devm_kzalloc(dev, sizeof(struct snd_soc_dai_link) * num_links, GFP_KERNEL);
565 if (drv_data->hs_cpu_id == I2S_SP) {
566 links[i].name = "acp-headset-codec";
567 links[i].id = HEADSET_BE_ID;
568 links[i].cpus = i2s_sp;
569 links[i].num_cpus = ARRAY_SIZE(i2s_sp);
570 links[i].platforms = platform_component;
571 links[i].num_platforms = ARRAY_SIZE(platform_component);
572 links[i].dpcm_playback = 1;
573 links[i].dpcm_capture = 1;
574 if (!drv_data->hs_codec_id) {
575 /* Use dummy codec if codec id not specified */
576 links[i].codecs = dummy_codec;
577 links[i].num_codecs = ARRAY_SIZE(dummy_codec);
579 if (drv_data->hs_codec_id == RT5682) {
580 links[i].codecs = rt5682;
581 links[i].num_codecs = ARRAY_SIZE(rt5682);
582 links[i].init = acp_card_rt5682_init;
583 links[i].ops = &acp_card_rt5682_ops;
585 if (drv_data->hs_codec_id == RT5682S) {
586 links[i].codecs = rt5682s;
587 links[i].num_codecs = ARRAY_SIZE(rt5682s);
588 links[i].init = acp_card_rt5682s_init;
589 links[i].ops = &acp_card_rt5682s_ops;
594 if (drv_data->amp_cpu_id == I2S_SP) {
595 links[i].name = "acp-amp-codec";
596 links[i].id = AMP_BE_ID;
597 links[i].cpus = i2s_sp;
598 links[i].num_cpus = ARRAY_SIZE(i2s_sp);
599 links[i].platforms = platform_component;
600 links[i].num_platforms = ARRAY_SIZE(platform_component);
601 links[i].dpcm_playback = 1;
602 if (!drv_data->amp_codec_id) {
603 /* Use dummy codec if codec id not specified */
604 links[i].codecs = dummy_codec;
605 links[i].num_codecs = ARRAY_SIZE(dummy_codec);
607 if (drv_data->amp_codec_id == RT1019) {
608 links[i].codecs = rt1019;
609 links[i].num_codecs = ARRAY_SIZE(rt1019);
610 links[i].ops = &acp_card_rt1019_ops;
611 links[i].init = acp_card_rt1019_init;
612 card->codec_conf = rt1019_conf;
613 card->num_configs = ARRAY_SIZE(rt1019_conf);
615 if (drv_data->amp_codec_id == MAX98360A) {
616 links[i].codecs = max98360a;
617 links[i].num_codecs = ARRAY_SIZE(max98360a);
618 links[i].ops = &acp_card_maxim_ops;
619 links[i].init = acp_card_maxim_init;
624 if (drv_data->dmic_cpu_id == DMIC) {
625 links[i].name = "acp-dmic-codec";
626 links[i].id = DMIC_BE_ID;
627 if (drv_data->dmic_codec_id == DMIC) {
628 links[i].codecs = dmic_codec;
629 links[i].num_codecs = ARRAY_SIZE(dmic_codec);
631 /* Use dummy codec if codec id not specified */
632 links[i].codecs = dummy_codec;
633 links[i].num_codecs = ARRAY_SIZE(dummy_codec);
635 links[i].cpus = pdm_dmic;
636 links[i].num_cpus = ARRAY_SIZE(pdm_dmic);
637 links[i].platforms = platform_component;
638 links[i].num_platforms = ARRAY_SIZE(platform_component);
639 links[i].ops = &acp_card_dmic_ops;
640 links[i].dpcm_capture = 1;
643 card->dai_link = links;
644 card->num_links = num_links;
648 EXPORT_SYMBOL_NS_GPL(acp_legacy_dai_links_create, SND_SOC_AMD_MACH);
650 MODULE_LICENSE("GPL v2");