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 "acp-mach.h" 28 29 #define PCO_PLAT_CLK 48000000 30 #define RT5682_PLL_FREQ (48000 * 512) 31 #define DUAL_CHANNEL 2 32 #define FOUR_CHANNEL 4 33 34 static struct snd_soc_jack pco_jack; 35 36 static const unsigned int channels[] = { 37 DUAL_CHANNEL, 38 }; 39 40 static const unsigned int rates[] = { 41 48000, 42 }; 43 44 static const struct snd_pcm_hw_constraint_list constraints_rates = { 45 .count = ARRAY_SIZE(rates), 46 .list = rates, 47 .mask = 0, 48 }; 49 50 static const struct snd_pcm_hw_constraint_list constraints_channels = { 51 .count = ARRAY_SIZE(channels), 52 .list = channels, 53 .mask = 0, 54 }; 55 56 static int acp_clk_enable(struct acp_card_drvdata *drvdata) 57 { 58 clk_set_rate(drvdata->wclk, 48000); 59 clk_set_rate(drvdata->bclk, 48000 * 64); 60 61 return clk_prepare_enable(drvdata->wclk); 62 } 63 64 /* Declare RT5682 codec components */ 65 SND_SOC_DAILINK_DEF(rt5682, 66 DAILINK_COMP_ARRAY(COMP_CODEC("i2c-10EC5682:00", "rt5682-aif1"))); 67 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" }, 72 }; 73 74 /* Define card ops for RT5682 CODEC */ 75 static int acp_card_rt5682_init(struct snd_soc_pcm_runtime *rtd) 76 { 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; 81 int ret; 82 83 dev_info(rtd->dev, "codec dai name = %s\n", codec_dai->name); 84 85 if (drvdata->hs_codec_id != RT5682) 86 return -EINVAL; 87 88 ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF 89 | SND_SOC_DAIFMT_CBP_CFP); 90 if (ret < 0) { 91 dev_err(rtd->card->dev, "Failed to set dai fmt: %d\n", ret); 92 return ret; 93 } 94 95 ret = snd_soc_dai_set_pll(codec_dai, RT5682_PLL2, RT5682_PLL2_S_MCLK, 96 PCO_PLAT_CLK, RT5682_PLL_FREQ); 97 if (ret < 0) { 98 dev_err(rtd->dev, "Failed to set codec PLL: %d\n", ret); 99 return ret; 100 } 101 102 ret = snd_soc_dai_set_sysclk(codec_dai, RT5682_SCLK_S_PLL2, 103 RT5682_PLL_FREQ, SND_SOC_CLOCK_IN); 104 if (ret < 0) { 105 dev_err(rtd->dev, "Failed to set codec SYSCLK: %d\n", ret); 106 return ret; 107 } 108 109 /* Set tdm/i2s1 master bclk ratio */ 110 ret = snd_soc_dai_set_bclk_ratio(codec_dai, 64); 111 if (ret < 0) { 112 dev_err(rtd->dev, "Failed to set rt5682 tdm bclk ratio: %d\n", ret); 113 return ret; 114 } 115 116 drvdata->wclk = clk_get(component->dev, "rt5682-dai-wclk"); 117 drvdata->bclk = clk_get(component->dev, "rt5682-dai-bclk"); 118 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, 123 &pco_jack); 124 if (ret) { 125 dev_err(card->dev, "HP jack creation failed %d\n", ret); 126 return ret; 127 } 128 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); 133 134 ret = snd_soc_component_set_jack(component, &pco_jack, NULL); 135 if (ret) { 136 dev_err(rtd->dev, "Headset Jack call-back failed: %d\n", ret); 137 return ret; 138 } 139 140 return snd_soc_dapm_add_routes(&rtd->card->dapm, rt5682_map, ARRAY_SIZE(rt5682_map)); 141 } 142 143 static int acp_card_hs_startup(struct snd_pcm_substream *substream) 144 { 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); 150 int ret; 151 152 ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF 153 | SND_SOC_DAIFMT_CBP_CFP); 154 if (ret < 0) { 155 dev_err(rtd->card->dev, "Failed to set dai fmt: %d\n", ret); 156 return ret; 157 } 158 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, 163 &constraints_rates); 164 165 ret = acp_clk_enable(drvdata); 166 if (ret < 0) 167 dev_err(rtd->card->dev, "Failed to enable HS clk: %d\n", ret); 168 169 return ret; 170 } 171 172 static void acp_card_shutdown(struct snd_pcm_substream *substream) 173 { 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; 177 178 clk_disable_unprepare(drvdata->wclk); 179 } 180 181 static const struct snd_soc_ops acp_card_rt5682_ops = { 182 .startup = acp_card_hs_startup, 183 .shutdown = acp_card_shutdown, 184 }; 185 186 /* Define RT5682S CODEC component*/ 187 SND_SOC_DAILINK_DEF(rt5682s, 188 DAILINK_COMP_ARRAY(COMP_CODEC("i2c-RTL5682:00", "rt5682s-aif1"))); 189 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" }, 194 }; 195 196 static int acp_card_rt5682s_init(struct snd_soc_pcm_runtime *rtd) 197 { 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; 202 int ret; 203 204 dev_info(rtd->dev, "codec dai name = %s\n", codec_dai->name); 205 206 if (drvdata->hs_codec_id != RT5682S) 207 return -EINVAL; 208 209 ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF 210 | SND_SOC_DAIFMT_CBP_CFP); 211 if (ret < 0) { 212 dev_err(rtd->card->dev, "Failed to set dai fmt: %d\n", ret); 213 return ret; 214 } 215 216 ret = snd_soc_dai_set_pll(codec_dai, RT5682S_PLL2, RT5682S_PLL_S_MCLK, 217 PCO_PLAT_CLK, RT5682_PLL_FREQ); 218 if (ret < 0) { 219 dev_err(rtd->dev, "Failed to set codec PLL: %d\n", ret); 220 return ret; 221 } 222 223 ret = snd_soc_dai_set_sysclk(codec_dai, RT5682S_SCLK_S_PLL2, 224 RT5682_PLL_FREQ, SND_SOC_CLOCK_IN); 225 if (ret < 0) { 226 dev_err(rtd->dev, "Failed to set codec SYSCLK: %d\n", ret); 227 return ret; 228 } 229 230 /* Set tdm/i2s1 master bclk ratio */ 231 ret = snd_soc_dai_set_bclk_ratio(codec_dai, 64); 232 if (ret < 0) { 233 dev_err(rtd->dev, "Failed to set rt5682 tdm bclk ratio: %d\n", ret); 234 return ret; 235 } 236 237 drvdata->wclk = clk_get(component->dev, "rt5682-dai-wclk"); 238 drvdata->bclk = clk_get(component->dev, "rt5682-dai-bclk"); 239 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, 244 &pco_jack); 245 if (ret) { 246 dev_err(card->dev, "HP jack creation failed %d\n", ret); 247 return ret; 248 } 249 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); 254 255 ret = snd_soc_component_set_jack(component, &pco_jack, NULL); 256 if (ret) { 257 dev_err(rtd->dev, "Headset Jack call-back failed: %d\n", ret); 258 return ret; 259 } 260 261 return snd_soc_dapm_add_routes(&rtd->card->dapm, rt5682s_map, ARRAY_SIZE(rt5682s_map)); 262 } 263 264 static const struct snd_soc_ops acp_card_rt5682s_ops = { 265 .startup = acp_card_hs_startup, 266 .shutdown = acp_card_shutdown, 267 }; 268 269 static const unsigned int dmic_channels[] = { 270 DUAL_CHANNEL, FOUR_CHANNEL, 271 }; 272 273 static const struct snd_pcm_hw_constraint_list dmic_constraints_channels = { 274 .count = ARRAY_SIZE(dmic_channels), 275 .list = dmic_channels, 276 .mask = 0, 277 }; 278 279 static int acp_card_dmic_startup(struct snd_pcm_substream *substream) 280 { 281 struct snd_pcm_runtime *runtime = substream->runtime; 282 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, 286 &constraints_rates); 287 288 return 0; 289 } 290 291 static const struct snd_soc_ops acp_card_dmic_ops = { 292 .startup = acp_card_dmic_startup, 293 }; 294 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"))); 299 300 static const struct snd_soc_dapm_route rt1019_map_lr[] = { 301 { "Left Spk", NULL, "Left SPO" }, 302 { "Right Spk", NULL, "Right SPO" }, 303 }; 304 305 static struct snd_soc_codec_conf rt1019_conf[] = { 306 { 307 .dlc = COMP_CODEC_CONF("i2c-10EC1019:01"), 308 .name_prefix = "Left", 309 }, 310 { 311 .dlc = COMP_CODEC_CONF("i2c-10EC1019:00"), 312 .name_prefix = "Right", 313 }, 314 }; 315 316 static int acp_card_rt1019_init(struct snd_soc_pcm_runtime *rtd) 317 { 318 struct snd_soc_card *card = rtd->card; 319 struct acp_card_drvdata *drvdata = card->drvdata; 320 321 if (drvdata->amp_codec_id != RT1019) 322 return -EINVAL; 323 324 return snd_soc_dapm_add_routes(&rtd->card->dapm, rt1019_map_lr, 325 ARRAY_SIZE(rt1019_map_lr)); 326 } 327 328 static int acp_card_rt1019_hw_params(struct snd_pcm_substream *substream, 329 struct snd_pcm_hw_params *params) 330 { 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; 336 337 srate = params_rate(params); 338 339 if (drvdata->amp_codec_id != RT1019) 340 return -EINVAL; 341 342 for_each_rtd_codec_dais(rtd, i, codec_dai) { 343 if (strcmp(codec_dai->name, "rt1019-aif")) 344 continue; 345 346 ret = snd_soc_dai_set_pll(codec_dai, 0, RT1019_PLL_S_BCLK, 347 64 * srate, 256 * srate); 348 if (ret < 0) 349 return ret; 350 351 ret = snd_soc_dai_set_sysclk(codec_dai, RT1019_SCLK_S_PLL, 352 256 * srate, SND_SOC_CLOCK_IN); 353 if (ret < 0) 354 return ret; 355 } 356 357 return 0; 358 } 359 360 static int acp_card_amp_startup(struct snd_pcm_substream *substream) 361 { 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; 366 int ret; 367 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, 372 &constraints_rates); 373 374 ret = acp_clk_enable(drvdata); 375 if (ret < 0) 376 dev_err(rtd->card->dev, "Failed to enable AMP clk: %d\n", ret); 377 378 return ret; 379 } 380 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, 385 }; 386 387 /* Declare Maxim codec components */ 388 SND_SOC_DAILINK_DEF(max98360a, 389 DAILINK_COMP_ARRAY(COMP_CODEC("MX98360A:00", "HiFi"))); 390 391 static const struct snd_soc_dapm_route max98360a_map[] = { 392 {"Spk", NULL, "Speaker"}, 393 }; 394 395 static int acp_card_maxim_init(struct snd_soc_pcm_runtime *rtd) 396 { 397 struct snd_soc_card *card = rtd->card; 398 struct acp_card_drvdata *drvdata = card->drvdata; 399 400 if (drvdata->amp_codec_id != MAX98360A) 401 return -EINVAL; 402 403 return snd_soc_dapm_add_routes(&rtd->card->dapm, max98360a_map, 404 ARRAY_SIZE(max98360a_map)); 405 } 406 407 static const struct snd_soc_ops acp_card_maxim_ops = { 408 .startup = acp_card_amp_startup, 409 .shutdown = acp_card_shutdown, 410 }; 411 412 /* Declare DMIC codec components */ 413 SND_SOC_DAILINK_DEF(dmic_codec, 414 DAILINK_COMP_ARRAY(COMP_CODEC("dmic-codec", "dmic-hifi"))); 415 416 /* Declare ACP CPU components */ 417 static struct snd_soc_dai_link_component dummy_codec[] = { 418 { 419 .name = "snd-soc-dummy", 420 .dai_name = "snd-soc-dummy-dai", 421 } 422 }; 423 424 static struct snd_soc_dai_link_component platform_component[] = { 425 { 426 .name = "acp_asoc_renoir.0", 427 } 428 }; 429 430 static struct snd_soc_dai_link_component sof_component[] = { 431 { 432 .name = "0000:04:00.5", 433 } 434 }; 435 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"))); 444 445 int acp_sofdsp_dai_links_create(struct snd_soc_card *card) 446 { 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; 451 452 if (drv_data->hs_cpu_id) 453 num_links++; 454 if (drv_data->amp_cpu_id) 455 num_links++; 456 if (drv_data->dmic_cpu_id) 457 num_links++; 458 459 links = devm_kzalloc(dev, sizeof(struct snd_soc_dai_link) * num_links, GFP_KERNEL); 460 if (!links) 461 return -ENOMEM; 462 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; 473 links[i].no_pcm = 1; 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); 478 } 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; 484 } 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; 490 } 491 i++; 492 } 493 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; 503 links[i].no_pcm = 1; 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); 508 } 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); 516 } 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; 522 } 523 i++; 524 } 525 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; 537 links[i].no_pcm = 1; 538 } 539 540 card->dai_link = links; 541 card->num_links = num_links; 542 543 return 0; 544 } 545 EXPORT_SYMBOL_NS_GPL(acp_sofdsp_dai_links_create, SND_SOC_AMD_MACH); 546 547 int acp_legacy_dai_links_create(struct snd_soc_card *card) 548 { 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; 553 554 if (drv_data->hs_cpu_id) 555 num_links++; 556 if (drv_data->amp_cpu_id) 557 num_links++; 558 if (drv_data->dmic_cpu_id) 559 num_links++; 560 561 links = devm_kzalloc(dev, sizeof(struct snd_soc_dai_link) * num_links, GFP_KERNEL); 562 if (!links) 563 return -ENOMEM; 564 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); 578 } 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; 584 } 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; 590 } 591 i++; 592 } 593 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); 606 } 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); 614 } 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; 620 } 621 i++; 622 } 623 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); 630 } else { 631 /* Use dummy codec if codec id not specified */ 632 links[i].codecs = dummy_codec; 633 links[i].num_codecs = ARRAY_SIZE(dummy_codec); 634 } 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; 641 } 642 643 card->dai_link = links; 644 card->num_links = num_links; 645 646 return 0; 647 } 648 EXPORT_SYMBOL_NS_GPL(acp_legacy_dai_links_create, SND_SOC_AMD_MACH); 649 650 MODULE_LICENSE("GPL v2"); 651