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