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, NULL, 0); 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, NULL, 0); 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 /* Declare RT1019 codec components */ 270 SND_SOC_DAILINK_DEF(rt1019, 271 DAILINK_COMP_ARRAY(COMP_CODEC("i2c-10EC1019:01", "rt1019-aif"), 272 COMP_CODEC("i2c-10EC1019:02", "rt1019-aif"))); 273 274 static const struct snd_soc_dapm_route rt1019_map_lr[] = { 275 { "Left Spk", NULL, "Left SPO" }, 276 { "Right Spk", NULL, "Right SPO" }, 277 }; 278 279 static struct snd_soc_codec_conf rt1019_conf[] = { 280 { 281 .dlc = COMP_CODEC_CONF("i2c-10EC1019:01"), 282 .name_prefix = "Left", 283 }, 284 { 285 .dlc = COMP_CODEC_CONF("i2c-10EC1019:02"), 286 .name_prefix = "Right", 287 }, 288 }; 289 290 static int acp_card_rt1019_init(struct snd_soc_pcm_runtime *rtd) 291 { 292 struct snd_soc_card *card = rtd->card; 293 struct acp_card_drvdata *drvdata = card->drvdata; 294 295 if (drvdata->amp_codec_id != RT1019) 296 return -EINVAL; 297 298 return snd_soc_dapm_add_routes(&rtd->card->dapm, rt1019_map_lr, 299 ARRAY_SIZE(rt1019_map_lr)); 300 } 301 302 static int acp_card_rt1019_hw_params(struct snd_pcm_substream *substream, 303 struct snd_pcm_hw_params *params) 304 { 305 struct snd_soc_pcm_runtime *rtd = substream->private_data; 306 struct snd_soc_card *card = rtd->card; 307 struct acp_card_drvdata *drvdata = card->drvdata; 308 struct snd_soc_dai *codec_dai; 309 int srate, i, ret = 0; 310 311 srate = params_rate(params); 312 313 if (drvdata->amp_codec_id != RT1019) 314 return -EINVAL; 315 316 for_each_rtd_codec_dais(rtd, i, codec_dai) { 317 if (strcmp(codec_dai->name, "rt1019-aif")) 318 continue; 319 320 ret = snd_soc_dai_set_pll(codec_dai, 0, RT1019_PLL_S_BCLK, 321 64 * srate, 256 * srate); 322 if (ret < 0) 323 return ret; 324 325 ret = snd_soc_dai_set_sysclk(codec_dai, RT1019_SCLK_S_PLL, 326 256 * srate, SND_SOC_CLOCK_IN); 327 if (ret < 0) 328 return ret; 329 } 330 331 return 0; 332 } 333 334 static int acp_card_amp_startup(struct snd_pcm_substream *substream) 335 { 336 struct snd_pcm_runtime *runtime = substream->runtime; 337 struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); 338 struct snd_soc_card *card = rtd->card; 339 struct acp_card_drvdata *drvdata = card->drvdata; 340 int ret; 341 342 runtime->hw.channels_max = DUAL_CHANNEL; 343 snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, 344 &constraints_channels); 345 snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, 346 &constraints_rates); 347 348 ret = acp_clk_enable(drvdata); 349 if (ret < 0) 350 dev_err(rtd->card->dev, "Failed to enable AMP clk: %d\n", ret); 351 352 return ret; 353 } 354 355 static const struct snd_soc_ops acp_card_rt1019_ops = { 356 .startup = acp_card_amp_startup, 357 .shutdown = acp_card_shutdown, 358 .hw_params = acp_card_rt1019_hw_params, 359 }; 360 361 /* Declare Maxim codec components */ 362 SND_SOC_DAILINK_DEF(max98360a, 363 DAILINK_COMP_ARRAY(COMP_CODEC("MX98360A:00", "HiFi"))); 364 365 static const struct snd_soc_dapm_route max98360a_map[] = { 366 {"Spk", NULL, "Speaker"}, 367 }; 368 369 static int acp_card_maxim_init(struct snd_soc_pcm_runtime *rtd) 370 { 371 struct snd_soc_card *card = rtd->card; 372 struct acp_card_drvdata *drvdata = card->drvdata; 373 374 if (drvdata->amp_codec_id != MAX98360A) 375 return -EINVAL; 376 377 return snd_soc_dapm_add_routes(&rtd->card->dapm, max98360a_map, 378 ARRAY_SIZE(max98360a_map)); 379 } 380 381 static const struct snd_soc_ops acp_card_maxim_ops = { 382 .startup = acp_card_amp_startup, 383 .shutdown = acp_card_shutdown, 384 }; 385 386 /* Declare DMIC codec components */ 387 SND_SOC_DAILINK_DEF(dmic_codec, 388 DAILINK_COMP_ARRAY(COMP_CODEC("dmic-codec", "dmic-hifi"))); 389 390 /* Declare ACP CPU components */ 391 static struct snd_soc_dai_link_component dummy_codec[] = { 392 { 393 .name = "snd-soc-dummy", 394 .dai_name = "snd-soc-dummy-dai", 395 } 396 }; 397 398 static struct snd_soc_dai_link_component platform_component[] = { 399 { 400 .name = "acp_asoc_renoir.0", 401 } 402 }; 403 404 static struct snd_soc_dai_link_component sof_component[] = { 405 { 406 .name = "0000:04:00.5", 407 } 408 }; 409 410 SND_SOC_DAILINK_DEF(i2s_sp, 411 DAILINK_COMP_ARRAY(COMP_CPU("acp-i2s-sp"))); 412 SND_SOC_DAILINK_DEF(sof_sp, 413 DAILINK_COMP_ARRAY(COMP_CPU("acp-sof-sp"))); 414 SND_SOC_DAILINK_DEF(sof_dmic, 415 DAILINK_COMP_ARRAY(COMP_CPU("acp-sof-dmic"))); 416 417 int acp_sofdsp_dai_links_create(struct snd_soc_card *card) 418 { 419 struct snd_soc_dai_link *links; 420 struct device *dev = card->dev; 421 struct acp_card_drvdata *drv_data = card->drvdata; 422 int i = 0, num_links = 0; 423 424 if (drv_data->hs_cpu_id) 425 num_links++; 426 if (drv_data->amp_cpu_id) 427 num_links++; 428 if (drv_data->dmic_cpu_id) 429 num_links++; 430 431 links = devm_kzalloc(dev, sizeof(struct snd_soc_dai_link) * num_links, GFP_KERNEL); 432 if (!links) 433 return -ENOMEM; 434 435 if (drv_data->hs_cpu_id == I2S_SP) { 436 links[i].name = "acp-headset-codec"; 437 links[i].id = HEADSET_BE_ID; 438 links[i].cpus = sof_sp; 439 links[i].num_cpus = ARRAY_SIZE(sof_sp); 440 links[i].platforms = sof_component; 441 links[i].num_platforms = ARRAY_SIZE(sof_component); 442 links[i].dpcm_playback = 1; 443 links[i].dpcm_capture = 1; 444 links[i].nonatomic = true; 445 links[i].no_pcm = 1; 446 if (!drv_data->hs_codec_id) { 447 /* Use dummy codec if codec id not specified */ 448 links[i].codecs = dummy_codec; 449 links[i].num_codecs = ARRAY_SIZE(dummy_codec); 450 } 451 if (drv_data->hs_codec_id == RT5682) { 452 links[i].codecs = rt5682; 453 links[i].num_codecs = ARRAY_SIZE(rt5682); 454 links[i].init = acp_card_rt5682_init; 455 links[i].ops = &acp_card_rt5682_ops; 456 } 457 if (drv_data->hs_codec_id == RT5682S) { 458 links[i].codecs = rt5682s; 459 links[i].num_codecs = ARRAY_SIZE(rt5682s); 460 links[i].init = acp_card_rt5682s_init; 461 links[i].ops = &acp_card_rt5682s_ops; 462 } 463 i++; 464 } 465 466 if (drv_data->amp_cpu_id == I2S_SP) { 467 links[i].name = "acp-amp-codec"; 468 links[i].id = AMP_BE_ID; 469 links[i].cpus = sof_sp; 470 links[i].num_cpus = ARRAY_SIZE(sof_sp); 471 links[i].platforms = sof_component; 472 links[i].num_platforms = ARRAY_SIZE(sof_component); 473 links[i].dpcm_playback = 1; 474 links[i].nonatomic = true; 475 links[i].no_pcm = 1; 476 if (!drv_data->amp_codec_id) { 477 /* Use dummy codec if codec id not specified */ 478 links[i].codecs = dummy_codec; 479 links[i].num_codecs = ARRAY_SIZE(dummy_codec); 480 } 481 if (drv_data->amp_codec_id == RT1019) { 482 links[i].codecs = rt1019; 483 links[i].num_codecs = ARRAY_SIZE(rt1019); 484 links[i].ops = &acp_card_rt1019_ops; 485 links[i].init = acp_card_rt1019_init; 486 card->codec_conf = rt1019_conf; 487 card->num_configs = ARRAY_SIZE(rt1019_conf); 488 } 489 if (drv_data->amp_codec_id == MAX98360A) { 490 links[i].codecs = max98360a; 491 links[i].num_codecs = ARRAY_SIZE(max98360a); 492 links[i].ops = &acp_card_maxim_ops; 493 links[i].init = acp_card_maxim_init; 494 } 495 i++; 496 } 497 498 if (drv_data->dmic_cpu_id == DMIC) { 499 links[i].name = "acp-dmic-codec"; 500 links[i].id = DMIC_BE_ID; 501 links[i].codecs = dmic_codec; 502 links[i].num_codecs = ARRAY_SIZE(dmic_codec); 503 links[i].cpus = sof_dmic; 504 links[i].num_cpus = ARRAY_SIZE(sof_dmic); 505 links[i].platforms = sof_component; 506 links[i].num_platforms = ARRAY_SIZE(sof_component); 507 links[i].dpcm_capture = 1; 508 links[i].nonatomic = true; 509 links[i].no_pcm = 1; 510 } 511 512 card->dai_link = links; 513 card->num_links = num_links; 514 515 return 0; 516 } 517 EXPORT_SYMBOL_NS_GPL(acp_sofdsp_dai_links_create, SND_SOC_AMD_MACH); 518 519 int acp_legacy_dai_links_create(struct snd_soc_card *card) 520 { 521 struct snd_soc_dai_link *links; 522 struct device *dev = card->dev; 523 struct acp_card_drvdata *drv_data = card->drvdata; 524 int i = 0, num_links = 0; 525 526 if (drv_data->hs_cpu_id) 527 num_links++; 528 if (drv_data->amp_cpu_id) 529 num_links++; 530 if (drv_data->dmic_cpu_id) 531 num_links++; 532 533 links = devm_kzalloc(dev, sizeof(struct snd_soc_dai_link) * num_links, GFP_KERNEL); 534 535 if (drv_data->hs_cpu_id == I2S_SP) { 536 links[i].name = "acp-headset-codec"; 537 links[i].id = HEADSET_BE_ID; 538 links[i].cpus = i2s_sp; 539 links[i].num_cpus = ARRAY_SIZE(i2s_sp); 540 links[i].platforms = platform_component; 541 links[i].num_platforms = ARRAY_SIZE(platform_component); 542 links[i].dpcm_playback = 1; 543 links[i].dpcm_capture = 1; 544 if (!drv_data->hs_codec_id) { 545 /* Use dummy codec if codec id not specified */ 546 links[i].codecs = dummy_codec; 547 links[i].num_codecs = ARRAY_SIZE(dummy_codec); 548 } 549 if (drv_data->hs_codec_id == RT5682) { 550 links[i].codecs = rt5682; 551 links[i].num_codecs = ARRAY_SIZE(rt5682); 552 links[i].init = acp_card_rt5682_init; 553 links[i].ops = &acp_card_rt5682_ops; 554 } 555 if (drv_data->hs_codec_id == RT5682S) { 556 links[i].codecs = rt5682s; 557 links[i].num_codecs = ARRAY_SIZE(rt5682s); 558 links[i].init = acp_card_rt5682s_init; 559 links[i].ops = &acp_card_rt5682s_ops; 560 } 561 i++; 562 } 563 564 if (drv_data->amp_cpu_id == I2S_SP) { 565 links[i].name = "acp-amp-codec"; 566 links[i].id = AMP_BE_ID; 567 links[i].cpus = i2s_sp; 568 links[i].num_cpus = ARRAY_SIZE(i2s_sp); 569 links[i].platforms = platform_component; 570 links[i].num_platforms = ARRAY_SIZE(platform_component); 571 links[i].dpcm_playback = 1; 572 if (!drv_data->amp_codec_id) { 573 /* Use dummy codec if codec id not specified */ 574 links[i].codecs = dummy_codec; 575 links[i].num_codecs = ARRAY_SIZE(dummy_codec); 576 } 577 if (drv_data->amp_codec_id == RT1019) { 578 links[i].codecs = rt1019; 579 links[i].num_codecs = ARRAY_SIZE(rt1019); 580 links[i].ops = &acp_card_rt1019_ops; 581 links[i].init = acp_card_rt1019_init; 582 card->codec_conf = rt1019_conf; 583 card->num_configs = ARRAY_SIZE(rt1019_conf); 584 } 585 if (drv_data->amp_codec_id == MAX98360A) { 586 links[i].codecs = max98360a; 587 links[i].num_codecs = ARRAY_SIZE(max98360a); 588 links[i].ops = &acp_card_maxim_ops; 589 links[i].init = acp_card_maxim_init; 590 } 591 } 592 593 card->dai_link = links; 594 card->num_links = num_links; 595 596 return 0; 597 } 598 EXPORT_SYMBOL_NS_GPL(acp_legacy_dai_links_create, SND_SOC_AMD_MACH); 599 600 MODULE_LICENSE("GPL v2"); 601