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 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 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 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 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 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 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 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 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 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_kzalloc(dev, sizeof(struct snd_soc_dai_link) * num_links, 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 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_kzalloc(dev, sizeof(struct snd_soc_dai_link) * num_links, 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