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 int event_spkr_handler(struct snd_soc_dapm_widget *w, 75 struct snd_kcontrol *k, int event) 76 { 77 struct snd_soc_dapm_context *dapm = w->dapm; 78 struct snd_soc_card *card = dapm->card; 79 struct acp_card_drvdata *drvdata = snd_soc_card_get_drvdata(card); 80 81 if (!gpio_is_valid(drvdata->gpio_spkr_en)) 82 return 0; 83 84 switch (event) { 85 case SND_SOC_DAPM_POST_PMU: 86 gpio_set_value(drvdata->gpio_spkr_en, 1); 87 break; 88 case SND_SOC_DAPM_PRE_PMD: 89 gpio_set_value(drvdata->gpio_spkr_en, 0); 90 break; 91 default: 92 dev_warn(card->dev, "%s invalid setting\n", __func__); 93 break; 94 } 95 return 0; 96 } 97 EXPORT_SYMBOL_NS_GPL(event_spkr_handler, SND_SOC_AMD_MACH); 98 99 /* Define card ops for RT5682 CODEC */ 100 static int acp_card_rt5682_init(struct snd_soc_pcm_runtime *rtd) 101 { 102 struct snd_soc_card *card = rtd->card; 103 struct acp_card_drvdata *drvdata = card->drvdata; 104 struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); 105 struct snd_soc_component *component = codec_dai->component; 106 int ret; 107 108 dev_info(rtd->dev, "codec dai name = %s\n", codec_dai->name); 109 110 if (drvdata->hs_codec_id != RT5682) 111 return -EINVAL; 112 113 ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF 114 | SND_SOC_DAIFMT_CBP_CFP); 115 if (ret < 0) { 116 dev_err(rtd->card->dev, "Failed to set dai fmt: %d\n", ret); 117 return ret; 118 } 119 120 ret = snd_soc_dai_set_pll(codec_dai, RT5682_PLL2, RT5682_PLL2_S_MCLK, 121 PCO_PLAT_CLK, RT5682_PLL_FREQ); 122 if (ret < 0) { 123 dev_err(rtd->dev, "Failed to set codec PLL: %d\n", ret); 124 return ret; 125 } 126 127 ret = snd_soc_dai_set_sysclk(codec_dai, RT5682_SCLK_S_PLL2, 128 RT5682_PLL_FREQ, SND_SOC_CLOCK_IN); 129 if (ret < 0) { 130 dev_err(rtd->dev, "Failed to set codec SYSCLK: %d\n", ret); 131 return ret; 132 } 133 134 /* Set tdm/i2s1 master bclk ratio */ 135 ret = snd_soc_dai_set_bclk_ratio(codec_dai, 64); 136 if (ret < 0) { 137 dev_err(rtd->dev, "Failed to set rt5682 tdm bclk ratio: %d\n", ret); 138 return ret; 139 } 140 141 drvdata->wclk = clk_get(component->dev, "rt5682-dai-wclk"); 142 drvdata->bclk = clk_get(component->dev, "rt5682-dai-bclk"); 143 144 ret = snd_soc_card_jack_new(card, "Headset Jack", 145 SND_JACK_HEADSET | SND_JACK_LINEOUT | 146 SND_JACK_BTN_0 | SND_JACK_BTN_1 | 147 SND_JACK_BTN_2 | SND_JACK_BTN_3, 148 &pco_jack, NULL, 0); 149 if (ret) { 150 dev_err(card->dev, "HP jack creation failed %d\n", ret); 151 return ret; 152 } 153 154 snd_jack_set_key(pco_jack.jack, SND_JACK_BTN_0, KEY_PLAYPAUSE); 155 snd_jack_set_key(pco_jack.jack, SND_JACK_BTN_1, KEY_VOICECOMMAND); 156 snd_jack_set_key(pco_jack.jack, SND_JACK_BTN_2, KEY_VOLUMEUP); 157 snd_jack_set_key(pco_jack.jack, SND_JACK_BTN_3, KEY_VOLUMEDOWN); 158 159 ret = snd_soc_component_set_jack(component, &pco_jack, NULL); 160 if (ret) { 161 dev_err(rtd->dev, "Headset Jack call-back failed: %d\n", ret); 162 return ret; 163 } 164 165 return snd_soc_dapm_add_routes(&rtd->card->dapm, rt5682_map, ARRAY_SIZE(rt5682_map)); 166 } 167 168 static int acp_card_hs_startup(struct snd_pcm_substream *substream) 169 { 170 struct snd_pcm_runtime *runtime = substream->runtime; 171 struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); 172 struct snd_soc_card *card = rtd->card; 173 struct acp_card_drvdata *drvdata = card->drvdata; 174 struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); 175 int ret; 176 177 ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF 178 | SND_SOC_DAIFMT_CBP_CFP); 179 if (ret < 0) { 180 dev_err(rtd->card->dev, "Failed to set dai fmt: %d\n", ret); 181 return ret; 182 } 183 184 runtime->hw.channels_max = DUAL_CHANNEL; 185 snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, 186 &constraints_channels); 187 snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, 188 &constraints_rates); 189 190 ret = acp_clk_enable(drvdata); 191 if (ret < 0) 192 dev_err(rtd->card->dev, "Failed to enable HS clk: %d\n", ret); 193 194 return ret; 195 } 196 197 static void acp_card_shutdown(struct snd_pcm_substream *substream) 198 { 199 struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); 200 struct snd_soc_card *card = rtd->card; 201 struct acp_card_drvdata *drvdata = card->drvdata; 202 203 clk_disable_unprepare(drvdata->wclk); 204 } 205 206 static const struct snd_soc_ops acp_card_rt5682_ops = { 207 .startup = acp_card_hs_startup, 208 .shutdown = acp_card_shutdown, 209 }; 210 211 /* Define RT5682S CODEC component*/ 212 SND_SOC_DAILINK_DEF(rt5682s, 213 DAILINK_COMP_ARRAY(COMP_CODEC("i2c-RTL5682:00", "rt5682s-aif1"))); 214 215 static const struct snd_soc_dapm_route rt5682s_map[] = { 216 { "Headphone Jack", NULL, "HPOL" }, 217 { "Headphone Jack", NULL, "HPOR" }, 218 { "IN1P", NULL, "Headset Mic" }, 219 }; 220 221 static int acp_card_rt5682s_init(struct snd_soc_pcm_runtime *rtd) 222 { 223 struct snd_soc_card *card = rtd->card; 224 struct acp_card_drvdata *drvdata = card->drvdata; 225 struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); 226 struct snd_soc_component *component = codec_dai->component; 227 int ret; 228 229 dev_info(rtd->dev, "codec dai name = %s\n", codec_dai->name); 230 231 if (drvdata->hs_codec_id != RT5682S) 232 return -EINVAL; 233 234 ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF 235 | SND_SOC_DAIFMT_CBP_CFP); 236 if (ret < 0) { 237 dev_err(rtd->card->dev, "Failed to set dai fmt: %d\n", ret); 238 return ret; 239 } 240 241 ret = snd_soc_dai_set_pll(codec_dai, RT5682S_PLL2, RT5682S_PLL_S_MCLK, 242 PCO_PLAT_CLK, RT5682_PLL_FREQ); 243 if (ret < 0) { 244 dev_err(rtd->dev, "Failed to set codec PLL: %d\n", ret); 245 return ret; 246 } 247 248 ret = snd_soc_dai_set_sysclk(codec_dai, RT5682S_SCLK_S_PLL2, 249 RT5682_PLL_FREQ, SND_SOC_CLOCK_IN); 250 if (ret < 0) { 251 dev_err(rtd->dev, "Failed to set codec SYSCLK: %d\n", ret); 252 return ret; 253 } 254 255 /* Set tdm/i2s1 master bclk ratio */ 256 ret = snd_soc_dai_set_bclk_ratio(codec_dai, 64); 257 if (ret < 0) { 258 dev_err(rtd->dev, "Failed to set rt5682 tdm bclk ratio: %d\n", ret); 259 return ret; 260 } 261 262 drvdata->wclk = clk_get(component->dev, "rt5682-dai-wclk"); 263 drvdata->bclk = clk_get(component->dev, "rt5682-dai-bclk"); 264 265 ret = snd_soc_card_jack_new(card, "Headset Jack", 266 SND_JACK_HEADSET | SND_JACK_LINEOUT | 267 SND_JACK_BTN_0 | SND_JACK_BTN_1 | 268 SND_JACK_BTN_2 | SND_JACK_BTN_3, 269 &pco_jack, NULL, 0); 270 if (ret) { 271 dev_err(card->dev, "HP jack creation failed %d\n", ret); 272 return ret; 273 } 274 275 snd_jack_set_key(pco_jack.jack, SND_JACK_BTN_0, KEY_PLAYPAUSE); 276 snd_jack_set_key(pco_jack.jack, SND_JACK_BTN_1, KEY_VOICECOMMAND); 277 snd_jack_set_key(pco_jack.jack, SND_JACK_BTN_2, KEY_VOLUMEUP); 278 snd_jack_set_key(pco_jack.jack, SND_JACK_BTN_3, KEY_VOLUMEDOWN); 279 280 ret = snd_soc_component_set_jack(component, &pco_jack, NULL); 281 if (ret) { 282 dev_err(rtd->dev, "Headset Jack call-back failed: %d\n", ret); 283 return ret; 284 } 285 286 return snd_soc_dapm_add_routes(&rtd->card->dapm, rt5682s_map, ARRAY_SIZE(rt5682s_map)); 287 } 288 289 static const struct snd_soc_ops acp_card_rt5682s_ops = { 290 .startup = acp_card_hs_startup, 291 .shutdown = acp_card_shutdown, 292 }; 293 294 /* Declare RT1019 codec components */ 295 SND_SOC_DAILINK_DEF(rt1019, 296 DAILINK_COMP_ARRAY(COMP_CODEC("i2c-10EC1019:00", "rt1019-aif"), 297 COMP_CODEC("i2c-10EC1019:01", "rt1019-aif"))); 298 299 static const struct snd_soc_dapm_route rt1019_map_lr[] = { 300 { "Left Spk", NULL, "Left SPO" }, 301 { "Right Spk", NULL, "Right SPO" }, 302 }; 303 304 static struct snd_soc_codec_conf rt1019_conf[] = { 305 { 306 .dlc = COMP_CODEC_CONF("i2c-10EC1019:00"), 307 .name_prefix = "Left", 308 }, 309 { 310 .dlc = COMP_CODEC_CONF("i2c-10EC1019:01"), 311 .name_prefix = "Right", 312 }, 313 }; 314 315 static int acp_card_rt1019_init(struct snd_soc_pcm_runtime *rtd) 316 { 317 struct snd_soc_card *card = rtd->card; 318 struct acp_card_drvdata *drvdata = card->drvdata; 319 320 if (drvdata->amp_codec_id != RT1019) 321 return -EINVAL; 322 323 return snd_soc_dapm_add_routes(&rtd->card->dapm, rt1019_map_lr, 324 ARRAY_SIZE(rt1019_map_lr)); 325 } 326 327 static int acp_card_rt1019_hw_params(struct snd_pcm_substream *substream, 328 struct snd_pcm_hw_params *params) 329 { 330 struct snd_soc_pcm_runtime *rtd = substream->private_data; 331 struct snd_soc_card *card = rtd->card; 332 struct acp_card_drvdata *drvdata = card->drvdata; 333 struct snd_soc_dai *codec_dai; 334 int srate, i, ret = 0; 335 336 srate = params_rate(params); 337 338 if (drvdata->amp_codec_id != RT1019) 339 return -EINVAL; 340 341 for_each_rtd_codec_dais(rtd, i, codec_dai) { 342 if (strcmp(codec_dai->name, "rt1019-aif")) 343 continue; 344 345 ret = snd_soc_dai_set_pll(codec_dai, 0, RT1019_PLL_S_BCLK, 346 64 * srate, 256 * srate); 347 if (ret < 0) 348 return ret; 349 350 ret = snd_soc_dai_set_sysclk(codec_dai, RT1019_SCLK_S_PLL, 351 256 * srate, SND_SOC_CLOCK_IN); 352 if (ret < 0) 353 return ret; 354 } 355 356 return 0; 357 } 358 359 static int acp_card_amp_startup(struct snd_pcm_substream *substream) 360 { 361 struct snd_pcm_runtime *runtime = substream->runtime; 362 struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); 363 struct snd_soc_card *card = rtd->card; 364 struct acp_card_drvdata *drvdata = card->drvdata; 365 int ret; 366 367 runtime->hw.channels_max = DUAL_CHANNEL; 368 snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, 369 &constraints_channels); 370 snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, 371 &constraints_rates); 372 373 ret = acp_clk_enable(drvdata); 374 if (ret < 0) 375 dev_err(rtd->card->dev, "Failed to enable AMP clk: %d\n", ret); 376 377 return ret; 378 } 379 380 static const struct snd_soc_ops acp_card_rt1019_ops = { 381 .startup = acp_card_amp_startup, 382 .shutdown = acp_card_shutdown, 383 .hw_params = acp_card_rt1019_hw_params, 384 }; 385 386 /* Declare Maxim codec components */ 387 SND_SOC_DAILINK_DEF(max98360a, 388 DAILINK_COMP_ARRAY(COMP_CODEC("MX98360A:00", "HiFi"))); 389 390 static const struct snd_soc_dapm_route max98360a_map[] = { 391 {"Spk", NULL, "Speaker"}, 392 }; 393 394 static int acp_card_maxim_init(struct snd_soc_pcm_runtime *rtd) 395 { 396 struct snd_soc_card *card = rtd->card; 397 struct acp_card_drvdata *drvdata = card->drvdata; 398 399 if (drvdata->amp_codec_id != MAX98360A) 400 return -EINVAL; 401 402 return snd_soc_dapm_add_routes(&rtd->card->dapm, max98360a_map, 403 ARRAY_SIZE(max98360a_map)); 404 } 405 406 static const struct snd_soc_ops acp_card_maxim_ops = { 407 .startup = acp_card_amp_startup, 408 .shutdown = acp_card_shutdown, 409 }; 410 411 /* Declare DMIC codec components */ 412 SND_SOC_DAILINK_DEF(dmic_codec, 413 DAILINK_COMP_ARRAY(COMP_CODEC("dmic-codec", "dmic-hifi"))); 414 415 /* Declare ACP CPU components */ 416 static struct snd_soc_dai_link_component dummy_codec[] = { 417 { 418 .name = "snd-soc-dummy", 419 .dai_name = "snd-soc-dummy-dai", 420 } 421 }; 422 423 static struct snd_soc_dai_link_component platform_component[] = { 424 { 425 .name = "acp_asoc_renoir.0", 426 } 427 }; 428 429 static struct snd_soc_dai_link_component sof_component[] = { 430 { 431 .name = "0000:04:00.5", 432 } 433 }; 434 435 SND_SOC_DAILINK_DEF(i2s_sp, 436 DAILINK_COMP_ARRAY(COMP_CPU("acp-i2s-sp"))); 437 SND_SOC_DAILINK_DEF(sof_sp, 438 DAILINK_COMP_ARRAY(COMP_CPU("acp-sof-sp"))); 439 SND_SOC_DAILINK_DEF(sof_dmic, 440 DAILINK_COMP_ARRAY(COMP_CPU("acp-sof-dmic"))); 441 442 int acp_sofdsp_dai_links_create(struct snd_soc_card *card) 443 { 444 struct snd_soc_dai_link *links; 445 struct device *dev = card->dev; 446 struct acp_card_drvdata *drv_data = card->drvdata; 447 int i = 0, num_links = 0; 448 449 if (drv_data->hs_cpu_id) 450 num_links++; 451 if (drv_data->amp_cpu_id) 452 num_links++; 453 if (drv_data->dmic_cpu_id) 454 num_links++; 455 456 links = devm_kzalloc(dev, sizeof(struct snd_soc_dai_link) * num_links, GFP_KERNEL); 457 if (!links) 458 return -ENOMEM; 459 460 if (drv_data->hs_cpu_id == I2S_SP) { 461 links[i].name = "acp-headset-codec"; 462 links[i].id = HEADSET_BE_ID; 463 links[i].cpus = sof_sp; 464 links[i].num_cpus = ARRAY_SIZE(sof_sp); 465 links[i].platforms = sof_component; 466 links[i].num_platforms = ARRAY_SIZE(sof_component); 467 links[i].dpcm_playback = 1; 468 links[i].dpcm_capture = 1; 469 links[i].nonatomic = true; 470 links[i].no_pcm = 1; 471 if (!drv_data->hs_codec_id) { 472 /* Use dummy codec if codec id not specified */ 473 links[i].codecs = dummy_codec; 474 links[i].num_codecs = ARRAY_SIZE(dummy_codec); 475 } 476 if (drv_data->hs_codec_id == RT5682) { 477 links[i].codecs = rt5682; 478 links[i].num_codecs = ARRAY_SIZE(rt5682); 479 links[i].init = acp_card_rt5682_init; 480 links[i].ops = &acp_card_rt5682_ops; 481 } 482 if (drv_data->hs_codec_id == RT5682S) { 483 links[i].codecs = rt5682s; 484 links[i].num_codecs = ARRAY_SIZE(rt5682s); 485 links[i].init = acp_card_rt5682s_init; 486 links[i].ops = &acp_card_rt5682s_ops; 487 } 488 i++; 489 } 490 491 if (drv_data->amp_cpu_id == I2S_SP) { 492 links[i].name = "acp-amp-codec"; 493 links[i].id = AMP_BE_ID; 494 links[i].cpus = sof_sp; 495 links[i].num_cpus = ARRAY_SIZE(sof_sp); 496 links[i].platforms = sof_component; 497 links[i].num_platforms = ARRAY_SIZE(sof_component); 498 links[i].dpcm_playback = 1; 499 links[i].nonatomic = true; 500 links[i].no_pcm = 1; 501 if (!drv_data->amp_codec_id) { 502 /* Use dummy codec if codec id not specified */ 503 links[i].codecs = dummy_codec; 504 links[i].num_codecs = ARRAY_SIZE(dummy_codec); 505 } 506 if (drv_data->amp_codec_id == RT1019) { 507 links[i].codecs = rt1019; 508 links[i].num_codecs = ARRAY_SIZE(rt1019); 509 links[i].ops = &acp_card_rt1019_ops; 510 links[i].init = acp_card_rt1019_init; 511 card->codec_conf = rt1019_conf; 512 card->num_configs = ARRAY_SIZE(rt1019_conf); 513 } 514 if (drv_data->amp_codec_id == MAX98360A) { 515 links[i].codecs = max98360a; 516 links[i].num_codecs = ARRAY_SIZE(max98360a); 517 links[i].ops = &acp_card_maxim_ops; 518 links[i].init = acp_card_maxim_init; 519 } 520 i++; 521 } 522 523 if (drv_data->dmic_cpu_id == DMIC) { 524 links[i].name = "acp-dmic-codec"; 525 links[i].id = DMIC_BE_ID; 526 links[i].codecs = dmic_codec; 527 links[i].num_codecs = ARRAY_SIZE(dmic_codec); 528 links[i].cpus = sof_dmic; 529 links[i].num_cpus = ARRAY_SIZE(sof_dmic); 530 links[i].platforms = sof_component; 531 links[i].num_platforms = ARRAY_SIZE(sof_component); 532 links[i].dpcm_capture = 1; 533 links[i].nonatomic = true; 534 links[i].no_pcm = 1; 535 } 536 537 card->dai_link = links; 538 card->num_links = num_links; 539 540 return 0; 541 } 542 EXPORT_SYMBOL_NS_GPL(acp_sofdsp_dai_links_create, SND_SOC_AMD_MACH); 543 544 int acp_legacy_dai_links_create(struct snd_soc_card *card) 545 { 546 struct snd_soc_dai_link *links; 547 struct device *dev = card->dev; 548 struct acp_card_drvdata *drv_data = card->drvdata; 549 int i = 0, num_links = 0; 550 551 if (drv_data->hs_cpu_id) 552 num_links++; 553 if (drv_data->amp_cpu_id) 554 num_links++; 555 if (drv_data->dmic_cpu_id) 556 num_links++; 557 558 links = devm_kzalloc(dev, sizeof(struct snd_soc_dai_link) * num_links, GFP_KERNEL); 559 560 if (drv_data->hs_cpu_id == I2S_SP) { 561 links[i].name = "acp-headset-codec"; 562 links[i].id = HEADSET_BE_ID; 563 links[i].cpus = i2s_sp; 564 links[i].num_cpus = ARRAY_SIZE(i2s_sp); 565 links[i].platforms = platform_component; 566 links[i].num_platforms = ARRAY_SIZE(platform_component); 567 links[i].dpcm_playback = 1; 568 links[i].dpcm_capture = 1; 569 if (!drv_data->hs_codec_id) { 570 /* Use dummy codec if codec id not specified */ 571 links[i].codecs = dummy_codec; 572 links[i].num_codecs = ARRAY_SIZE(dummy_codec); 573 } 574 if (drv_data->hs_codec_id == RT5682) { 575 links[i].codecs = rt5682; 576 links[i].num_codecs = ARRAY_SIZE(rt5682); 577 links[i].init = acp_card_rt5682_init; 578 links[i].ops = &acp_card_rt5682_ops; 579 } 580 if (drv_data->hs_codec_id == RT5682S) { 581 links[i].codecs = rt5682s; 582 links[i].num_codecs = ARRAY_SIZE(rt5682s); 583 links[i].init = acp_card_rt5682s_init; 584 links[i].ops = &acp_card_rt5682s_ops; 585 } 586 i++; 587 } 588 589 if (drv_data->amp_cpu_id == I2S_SP) { 590 links[i].name = "acp-amp-codec"; 591 links[i].id = AMP_BE_ID; 592 links[i].cpus = i2s_sp; 593 links[i].num_cpus = ARRAY_SIZE(i2s_sp); 594 links[i].platforms = platform_component; 595 links[i].num_platforms = ARRAY_SIZE(platform_component); 596 links[i].dpcm_playback = 1; 597 if (!drv_data->amp_codec_id) { 598 /* Use dummy codec if codec id not specified */ 599 links[i].codecs = dummy_codec; 600 links[i].num_codecs = ARRAY_SIZE(dummy_codec); 601 } 602 if (drv_data->amp_codec_id == RT1019) { 603 links[i].codecs = rt1019; 604 links[i].num_codecs = ARRAY_SIZE(rt1019); 605 links[i].ops = &acp_card_rt1019_ops; 606 links[i].init = acp_card_rt1019_init; 607 card->codec_conf = rt1019_conf; 608 card->num_configs = ARRAY_SIZE(rt1019_conf); 609 } 610 if (drv_data->amp_codec_id == MAX98360A) { 611 links[i].codecs = max98360a; 612 links[i].num_codecs = ARRAY_SIZE(max98360a); 613 links[i].ops = &acp_card_maxim_ops; 614 links[i].init = acp_card_maxim_init; 615 } 616 } 617 618 card->dai_link = links; 619 card->num_links = num_links; 620 621 return 0; 622 } 623 EXPORT_SYMBOL_NS_GPL(acp_legacy_dai_links_create, SND_SOC_AMD_MACH); 624 625 MODULE_LICENSE("GPL v2"); 626