1 // SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) 2 // Copyright(c) 2023 Intel Corporation. All rights reserved. 3 4 /* 5 * Soundwire Intel ops for LunarLake 6 */ 7 8 #include <linux/acpi.h> 9 #include <linux/device.h> 10 #include <linux/soundwire/sdw_registers.h> 11 #include <linux/soundwire/sdw.h> 12 #include <linux/soundwire/sdw_intel.h> 13 #include <sound/hdaudio.h> 14 #include <sound/hda-mlink.h> 15 #include <sound/hda_register.h> 16 #include <sound/pcm_params.h> 17 #include "cadence_master.h" 18 #include "bus.h" 19 #include "intel.h" 20 21 /* 22 * shim vendor-specific (vs) ops 23 */ 24 25 static void intel_shim_vs_init(struct sdw_intel *sdw) 26 { 27 void __iomem *shim_vs = sdw->link_res->shim_vs; 28 struct sdw_bus *bus = &sdw->cdns.bus; 29 struct sdw_intel_prop *intel_prop; 30 u16 doaise; 31 u16 doais; 32 u16 dodse; 33 u16 dods; 34 u16 act; 35 36 intel_prop = bus->vendor_specific_prop; 37 doaise = intel_prop->doaise; 38 doais = intel_prop->doais; 39 dodse = intel_prop->dodse; 40 dods = intel_prop->dods; 41 42 act = intel_readw(shim_vs, SDW_SHIM2_INTEL_VS_ACTMCTL); 43 u16p_replace_bits(&act, doaise, SDW_SHIM2_INTEL_VS_ACTMCTL_DOAISE); 44 u16p_replace_bits(&act, doais, SDW_SHIM2_INTEL_VS_ACTMCTL_DOAIS); 45 u16p_replace_bits(&act, dodse, SDW_SHIM2_INTEL_VS_ACTMCTL_DODSE); 46 u16p_replace_bits(&act, dods, SDW_SHIM2_INTEL_VS_ACTMCTL_DODS); 47 act |= SDW_SHIM2_INTEL_VS_ACTMCTL_DACTQE; 48 intel_writew(shim_vs, SDW_SHIM2_INTEL_VS_ACTMCTL, act); 49 usleep_range(10, 15); 50 } 51 52 static void intel_shim_vs_set_clock_source(struct sdw_intel *sdw, u32 source) 53 { 54 void __iomem *shim_vs = sdw->link_res->shim_vs; 55 u32 val; 56 57 val = intel_readl(shim_vs, SDW_SHIM2_INTEL_VS_LVSCTL); 58 59 u32p_replace_bits(&val, source, SDW_SHIM2_INTEL_VS_LVSCTL_MLCS); 60 61 intel_writel(shim_vs, SDW_SHIM2_INTEL_VS_LVSCTL, val); 62 63 dev_dbg(sdw->cdns.dev, "clock source %d LVSCTL %#x\n", source, val); 64 } 65 66 static int intel_shim_check_wake(struct sdw_intel *sdw) 67 { 68 /* 69 * We follow the HDaudio example and resume unconditionally 70 * without checking the WAKESTS bit for that specific link 71 */ 72 73 return 1; 74 } 75 76 static void intel_shim_wake(struct sdw_intel *sdw, bool wake_enable) 77 { 78 u16 lsdiid = 0; 79 u16 wake_en; 80 u16 wake_sts; 81 int ret; 82 83 mutex_lock(sdw->link_res->shim_lock); 84 85 ret = hdac_bus_eml_sdw_get_lsdiid_unlocked(sdw->link_res->hbus, sdw->instance, &lsdiid); 86 if (ret < 0) 87 goto unlock; 88 89 wake_en = snd_hdac_chip_readw(sdw->link_res->hbus, WAKEEN); 90 91 if (wake_enable) { 92 /* Enable the wakeup */ 93 wake_en |= lsdiid; 94 95 snd_hdac_chip_writew(sdw->link_res->hbus, WAKEEN, wake_en); 96 } else { 97 /* Disable the wake up interrupt */ 98 wake_en &= ~lsdiid; 99 snd_hdac_chip_writew(sdw->link_res->hbus, WAKEEN, wake_en); 100 101 /* Clear wake status (W1C) */ 102 wake_sts = snd_hdac_chip_readw(sdw->link_res->hbus, STATESTS); 103 wake_sts |= lsdiid; 104 snd_hdac_chip_writew(sdw->link_res->hbus, STATESTS, wake_sts); 105 } 106 unlock: 107 mutex_unlock(sdw->link_res->shim_lock); 108 } 109 110 static int intel_link_power_up(struct sdw_intel *sdw) 111 { 112 struct sdw_bus *bus = &sdw->cdns.bus; 113 struct sdw_master_prop *prop = &bus->prop; 114 u32 *shim_mask = sdw->link_res->shim_mask; 115 unsigned int link_id = sdw->instance; 116 u32 clock_source; 117 u32 syncprd; 118 int ret; 119 120 if (prop->mclk_freq % 6000000) { 121 if (prop->mclk_freq % 2400000) { 122 syncprd = SDW_SHIM_SYNC_SYNCPRD_VAL_24_576; 123 clock_source = SDW_SHIM2_MLCS_CARDINAL_CLK; 124 } else { 125 syncprd = SDW_SHIM_SYNC_SYNCPRD_VAL_38_4; 126 clock_source = SDW_SHIM2_MLCS_XTAL_CLK; 127 } 128 } else { 129 syncprd = SDW_SHIM_SYNC_SYNCPRD_VAL_96; 130 clock_source = SDW_SHIM2_MLCS_AUDIO_PLL_CLK; 131 } 132 133 mutex_lock(sdw->link_res->shim_lock); 134 135 ret = hdac_bus_eml_sdw_power_up_unlocked(sdw->link_res->hbus, link_id); 136 if (ret < 0) { 137 dev_err(sdw->cdns.dev, "%s: hdac_bus_eml_sdw_power_up failed: %d\n", 138 __func__, ret); 139 goto out; 140 } 141 142 intel_shim_vs_set_clock_source(sdw, clock_source); 143 144 if (!*shim_mask) { 145 /* we first need to program the SyncPRD/CPU registers */ 146 dev_dbg(sdw->cdns.dev, "first link up, programming SYNCPRD\n"); 147 148 ret = hdac_bus_eml_sdw_set_syncprd_unlocked(sdw->link_res->hbus, syncprd); 149 if (ret < 0) { 150 dev_err(sdw->cdns.dev, "%s: hdac_bus_eml_sdw_set_syncprd failed: %d\n", 151 __func__, ret); 152 goto out; 153 } 154 155 /* SYNCPU will change once link is active */ 156 ret = hdac_bus_eml_sdw_wait_syncpu_unlocked(sdw->link_res->hbus); 157 if (ret < 0) { 158 dev_err(sdw->cdns.dev, "%s: hdac_bus_eml_sdw_wait_syncpu failed: %d\n", 159 __func__, ret); 160 goto out; 161 } 162 } 163 164 *shim_mask |= BIT(link_id); 165 166 sdw->cdns.link_up = true; 167 168 intel_shim_vs_init(sdw); 169 170 out: 171 mutex_unlock(sdw->link_res->shim_lock); 172 173 return ret; 174 } 175 176 static int intel_link_power_down(struct sdw_intel *sdw) 177 { 178 u32 *shim_mask = sdw->link_res->shim_mask; 179 unsigned int link_id = sdw->instance; 180 int ret; 181 182 mutex_lock(sdw->link_res->shim_lock); 183 184 sdw->cdns.link_up = false; 185 186 *shim_mask &= ~BIT(link_id); 187 188 ret = hdac_bus_eml_sdw_power_down_unlocked(sdw->link_res->hbus, link_id); 189 if (ret < 0) { 190 dev_err(sdw->cdns.dev, "%s: hdac_bus_eml_sdw_power_down failed: %d\n", 191 __func__, ret); 192 193 /* 194 * we leave the sdw->cdns.link_up flag as false since we've disabled 195 * the link at this point and cannot handle interrupts any longer. 196 */ 197 } 198 199 mutex_unlock(sdw->link_res->shim_lock); 200 201 return ret; 202 } 203 204 static void intel_sync_arm(struct sdw_intel *sdw) 205 { 206 unsigned int link_id = sdw->instance; 207 208 mutex_lock(sdw->link_res->shim_lock); 209 210 hdac_bus_eml_sdw_sync_arm_unlocked(sdw->link_res->hbus, link_id); 211 212 mutex_unlock(sdw->link_res->shim_lock); 213 } 214 215 static int intel_sync_go_unlocked(struct sdw_intel *sdw) 216 { 217 int ret; 218 219 ret = hdac_bus_eml_sdw_sync_go_unlocked(sdw->link_res->hbus); 220 if (ret < 0) 221 dev_err(sdw->cdns.dev, "%s: SyncGO clear failed: %d\n", __func__, ret); 222 223 return ret; 224 } 225 226 static int intel_sync_go(struct sdw_intel *sdw) 227 { 228 int ret; 229 230 mutex_lock(sdw->link_res->shim_lock); 231 232 ret = intel_sync_go_unlocked(sdw); 233 234 mutex_unlock(sdw->link_res->shim_lock); 235 236 return ret; 237 } 238 239 static bool intel_check_cmdsync_unlocked(struct sdw_intel *sdw) 240 { 241 return hdac_bus_eml_sdw_check_cmdsync_unlocked(sdw->link_res->hbus); 242 } 243 244 /* DAI callbacks */ 245 static int intel_params_stream(struct sdw_intel *sdw, 246 struct snd_pcm_substream *substream, 247 struct snd_soc_dai *dai, 248 struct snd_pcm_hw_params *hw_params, 249 int link_id, int alh_stream_id) 250 { 251 struct sdw_intel_link_res *res = sdw->link_res; 252 struct sdw_intel_stream_params_data params_data; 253 254 params_data.substream = substream; 255 params_data.dai = dai; 256 params_data.hw_params = hw_params; 257 params_data.link_id = link_id; 258 params_data.alh_stream_id = alh_stream_id; 259 260 if (res->ops && res->ops->params_stream && res->dev) 261 return res->ops->params_stream(res->dev, 262 ¶ms_data); 263 return -EIO; 264 } 265 266 static int intel_free_stream(struct sdw_intel *sdw, 267 struct snd_pcm_substream *substream, 268 struct snd_soc_dai *dai, 269 int link_id) 270 271 { 272 struct sdw_intel_link_res *res = sdw->link_res; 273 struct sdw_intel_stream_free_data free_data; 274 275 free_data.substream = substream; 276 free_data.dai = dai; 277 free_data.link_id = link_id; 278 279 if (res->ops && res->ops->free_stream && res->dev) 280 return res->ops->free_stream(res->dev, 281 &free_data); 282 283 return 0; 284 } 285 286 /* 287 * DAI operations 288 */ 289 static int intel_hw_params(struct snd_pcm_substream *substream, 290 struct snd_pcm_hw_params *params, 291 struct snd_soc_dai *dai) 292 { 293 struct sdw_cdns *cdns = snd_soc_dai_get_drvdata(dai); 294 struct sdw_intel *sdw = cdns_to_intel(cdns); 295 struct sdw_cdns_dai_runtime *dai_runtime; 296 struct sdw_cdns_pdi *pdi; 297 struct sdw_stream_config sconfig; 298 struct sdw_port_config *pconfig; 299 int ch, dir; 300 int ret; 301 302 dai_runtime = cdns->dai_runtime_array[dai->id]; 303 if (!dai_runtime) 304 return -EIO; 305 306 ch = params_channels(params); 307 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) 308 dir = SDW_DATA_DIR_RX; 309 else 310 dir = SDW_DATA_DIR_TX; 311 312 pdi = sdw_cdns_alloc_pdi(cdns, &cdns->pcm, ch, dir, dai->id); 313 314 if (!pdi) { 315 ret = -EINVAL; 316 goto error; 317 } 318 319 /* use same definitions for alh_id as previous generations */ 320 pdi->intel_alh_id = (sdw->instance * 16) + pdi->num + 3; 321 if (pdi->num >= 2) 322 pdi->intel_alh_id += 2; 323 324 /* the SHIM will be configured in the callback functions */ 325 326 sdw_cdns_config_stream(cdns, ch, dir, pdi); 327 328 /* store pdi and state, may be needed in prepare step */ 329 dai_runtime->paused = false; 330 dai_runtime->suspended = false; 331 dai_runtime->pdi = pdi; 332 333 /* Inform DSP about PDI stream number */ 334 ret = intel_params_stream(sdw, substream, dai, params, 335 sdw->instance, 336 pdi->intel_alh_id); 337 if (ret) 338 goto error; 339 340 sconfig.direction = dir; 341 sconfig.ch_count = ch; 342 sconfig.frame_rate = params_rate(params); 343 sconfig.type = dai_runtime->stream_type; 344 345 sconfig.bps = snd_pcm_format_width(params_format(params)); 346 347 /* Port configuration */ 348 pconfig = kzalloc(sizeof(*pconfig), GFP_KERNEL); 349 if (!pconfig) { 350 ret = -ENOMEM; 351 goto error; 352 } 353 354 pconfig->num = pdi->num; 355 pconfig->ch_mask = (1 << ch) - 1; 356 357 ret = sdw_stream_add_master(&cdns->bus, &sconfig, 358 pconfig, 1, dai_runtime->stream); 359 if (ret) 360 dev_err(cdns->dev, "add master to stream failed:%d\n", ret); 361 362 kfree(pconfig); 363 error: 364 return ret; 365 } 366 367 static int intel_prepare(struct snd_pcm_substream *substream, 368 struct snd_soc_dai *dai) 369 { 370 struct sdw_cdns *cdns = snd_soc_dai_get_drvdata(dai); 371 struct sdw_intel *sdw = cdns_to_intel(cdns); 372 struct sdw_cdns_dai_runtime *dai_runtime; 373 int ch, dir; 374 int ret = 0; 375 376 dai_runtime = cdns->dai_runtime_array[dai->id]; 377 if (!dai_runtime) { 378 dev_err(dai->dev, "failed to get dai runtime in %s\n", 379 __func__); 380 return -EIO; 381 } 382 383 if (dai_runtime->suspended) { 384 struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); 385 struct snd_pcm_hw_params *hw_params; 386 387 hw_params = &rtd->dpcm[substream->stream].hw_params; 388 389 dai_runtime->suspended = false; 390 391 /* 392 * .prepare() is called after system resume, where we 393 * need to reinitialize the SHIM/ALH/Cadence IP. 394 * .prepare() is also called to deal with underflows, 395 * but in those cases we cannot touch ALH/SHIM 396 * registers 397 */ 398 399 /* configure stream */ 400 ch = params_channels(hw_params); 401 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) 402 dir = SDW_DATA_DIR_RX; 403 else 404 dir = SDW_DATA_DIR_TX; 405 406 /* the SHIM will be configured in the callback functions */ 407 408 sdw_cdns_config_stream(cdns, ch, dir, dai_runtime->pdi); 409 410 /* Inform DSP about PDI stream number */ 411 ret = intel_params_stream(sdw, substream, dai, 412 hw_params, 413 sdw->instance, 414 dai_runtime->pdi->intel_alh_id); 415 } 416 417 return ret; 418 } 419 420 static int 421 intel_hw_free(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) 422 { 423 struct sdw_cdns *cdns = snd_soc_dai_get_drvdata(dai); 424 struct sdw_intel *sdw = cdns_to_intel(cdns); 425 struct sdw_cdns_dai_runtime *dai_runtime; 426 int ret; 427 428 dai_runtime = cdns->dai_runtime_array[dai->id]; 429 if (!dai_runtime) 430 return -EIO; 431 432 /* 433 * The sdw stream state will transition to RELEASED when stream-> 434 * master_list is empty. So the stream state will transition to 435 * DEPREPARED for the first cpu-dai and to RELEASED for the last 436 * cpu-dai. 437 */ 438 ret = sdw_stream_remove_master(&cdns->bus, dai_runtime->stream); 439 if (ret < 0) { 440 dev_err(dai->dev, "remove master from stream %s failed: %d\n", 441 dai_runtime->stream->name, ret); 442 return ret; 443 } 444 445 ret = intel_free_stream(sdw, substream, dai, sdw->instance); 446 if (ret < 0) { 447 dev_err(dai->dev, "intel_free_stream: failed %d\n", ret); 448 return ret; 449 } 450 451 dai_runtime->pdi = NULL; 452 453 return 0; 454 } 455 456 static int intel_pcm_set_sdw_stream(struct snd_soc_dai *dai, 457 void *stream, int direction) 458 { 459 return cdns_set_sdw_stream(dai, stream, direction); 460 } 461 462 static void *intel_get_sdw_stream(struct snd_soc_dai *dai, 463 int direction) 464 { 465 struct sdw_cdns *cdns = snd_soc_dai_get_drvdata(dai); 466 struct sdw_cdns_dai_runtime *dai_runtime; 467 468 dai_runtime = cdns->dai_runtime_array[dai->id]; 469 if (!dai_runtime) 470 return ERR_PTR(-EINVAL); 471 472 return dai_runtime->stream; 473 } 474 475 static int intel_trigger(struct snd_pcm_substream *substream, int cmd, struct snd_soc_dai *dai) 476 { 477 struct sdw_cdns *cdns = snd_soc_dai_get_drvdata(dai); 478 struct sdw_intel *sdw = cdns_to_intel(cdns); 479 struct sdw_intel_link_res *res = sdw->link_res; 480 struct sdw_cdns_dai_runtime *dai_runtime; 481 int ret = 0; 482 483 /* 484 * The .trigger callback is used to program HDaudio DMA and send required IPC to audio 485 * firmware. 486 */ 487 if (res->ops && res->ops->trigger) { 488 ret = res->ops->trigger(substream, cmd, dai); 489 if (ret < 0) 490 return ret; 491 } 492 493 dai_runtime = cdns->dai_runtime_array[dai->id]; 494 if (!dai_runtime) { 495 dev_err(dai->dev, "failed to get dai runtime in %s\n", 496 __func__); 497 return -EIO; 498 } 499 500 switch (cmd) { 501 case SNDRV_PCM_TRIGGER_SUSPEND: 502 503 /* 504 * The .prepare callback is used to deal with xruns and resume operations. 505 * In the case of xruns, the DMAs and SHIM registers cannot be touched, 506 * but for resume operations the DMAs and SHIM registers need to be initialized. 507 * the .trigger callback is used to track the suspend case only. 508 */ 509 510 dai_runtime->suspended = true; 511 512 break; 513 514 case SNDRV_PCM_TRIGGER_PAUSE_PUSH: 515 dai_runtime->paused = true; 516 break; 517 case SNDRV_PCM_TRIGGER_STOP: 518 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: 519 dai_runtime->paused = false; 520 break; 521 default: 522 break; 523 } 524 525 return ret; 526 } 527 528 static const struct snd_soc_dai_ops intel_pcm_dai_ops = { 529 .hw_params = intel_hw_params, 530 .prepare = intel_prepare, 531 .hw_free = intel_hw_free, 532 .trigger = intel_trigger, 533 .set_stream = intel_pcm_set_sdw_stream, 534 .get_stream = intel_get_sdw_stream, 535 }; 536 537 static const struct snd_soc_component_driver dai_component = { 538 .name = "soundwire", 539 }; 540 541 /* 542 * PDI routines 543 */ 544 static void intel_pdi_init(struct sdw_intel *sdw, 545 struct sdw_cdns_stream_config *config) 546 { 547 void __iomem *shim = sdw->link_res->shim; 548 int pcm_cap; 549 550 /* PCM Stream Capability */ 551 pcm_cap = intel_readw(shim, SDW_SHIM2_PCMSCAP); 552 553 config->pcm_bd = FIELD_GET(SDW_SHIM2_PCMSCAP_BSS, pcm_cap); 554 config->pcm_in = FIELD_GET(SDW_SHIM2_PCMSCAP_ISS, pcm_cap); 555 config->pcm_out = FIELD_GET(SDW_SHIM2_PCMSCAP_ISS, pcm_cap); 556 557 dev_dbg(sdw->cdns.dev, "PCM cap bd:%d in:%d out:%d\n", 558 config->pcm_bd, config->pcm_in, config->pcm_out); 559 } 560 561 static int 562 intel_pdi_get_ch_cap(struct sdw_intel *sdw, unsigned int pdi_num) 563 { 564 void __iomem *shim = sdw->link_res->shim; 565 566 /* zero based values for channel count in register */ 567 return intel_readw(shim, SDW_SHIM2_PCMSYCHC(pdi_num)) + 1; 568 } 569 570 static void intel_pdi_get_ch_update(struct sdw_intel *sdw, 571 struct sdw_cdns_pdi *pdi, 572 unsigned int num_pdi, 573 unsigned int *num_ch) 574 { 575 int ch_count = 0; 576 int i; 577 578 for (i = 0; i < num_pdi; i++) { 579 pdi->ch_count = intel_pdi_get_ch_cap(sdw, pdi->num); 580 ch_count += pdi->ch_count; 581 pdi++; 582 } 583 584 *num_ch = ch_count; 585 } 586 587 static void intel_pdi_stream_ch_update(struct sdw_intel *sdw, 588 struct sdw_cdns_streams *stream) 589 { 590 intel_pdi_get_ch_update(sdw, stream->bd, stream->num_bd, 591 &stream->num_ch_bd); 592 593 intel_pdi_get_ch_update(sdw, stream->in, stream->num_in, 594 &stream->num_ch_in); 595 596 intel_pdi_get_ch_update(sdw, stream->out, stream->num_out, 597 &stream->num_ch_out); 598 } 599 600 static int intel_create_dai(struct sdw_cdns *cdns, 601 struct snd_soc_dai_driver *dais, 602 enum intel_pdi_type type, 603 u32 num, u32 off, u32 max_ch) 604 { 605 int i; 606 607 if (!num) 608 return 0; 609 610 for (i = off; i < (off + num); i++) { 611 dais[i].name = devm_kasprintf(cdns->dev, GFP_KERNEL, 612 "SDW%d Pin%d", 613 cdns->instance, i); 614 if (!dais[i].name) 615 return -ENOMEM; 616 617 if (type == INTEL_PDI_BD || type == INTEL_PDI_OUT) { 618 dais[i].playback.channels_min = 1; 619 dais[i].playback.channels_max = max_ch; 620 } 621 622 if (type == INTEL_PDI_BD || type == INTEL_PDI_IN) { 623 dais[i].capture.channels_min = 1; 624 dais[i].capture.channels_max = max_ch; 625 } 626 627 dais[i].ops = &intel_pcm_dai_ops; 628 } 629 630 return 0; 631 } 632 633 static int intel_register_dai(struct sdw_intel *sdw) 634 { 635 struct sdw_cdns_dai_runtime **dai_runtime_array; 636 struct sdw_cdns_stream_config config; 637 struct sdw_cdns *cdns = &sdw->cdns; 638 struct sdw_cdns_streams *stream; 639 struct snd_soc_dai_driver *dais; 640 int num_dai; 641 int ret; 642 int off = 0; 643 644 /* Read the PDI config and initialize cadence PDI */ 645 intel_pdi_init(sdw, &config); 646 ret = sdw_cdns_pdi_init(cdns, config); 647 if (ret) 648 return ret; 649 650 intel_pdi_stream_ch_update(sdw, &sdw->cdns.pcm); 651 652 /* DAIs are created based on total number of PDIs supported */ 653 num_dai = cdns->pcm.num_pdi; 654 655 dai_runtime_array = devm_kcalloc(cdns->dev, num_dai, 656 sizeof(struct sdw_cdns_dai_runtime *), 657 GFP_KERNEL); 658 if (!dai_runtime_array) 659 return -ENOMEM; 660 cdns->dai_runtime_array = dai_runtime_array; 661 662 dais = devm_kcalloc(cdns->dev, num_dai, sizeof(*dais), GFP_KERNEL); 663 if (!dais) 664 return -ENOMEM; 665 666 /* Create PCM DAIs */ 667 stream = &cdns->pcm; 668 669 ret = intel_create_dai(cdns, dais, INTEL_PDI_IN, cdns->pcm.num_in, 670 off, stream->num_ch_in); 671 if (ret) 672 return ret; 673 674 off += cdns->pcm.num_in; 675 ret = intel_create_dai(cdns, dais, INTEL_PDI_OUT, cdns->pcm.num_out, 676 off, stream->num_ch_out); 677 if (ret) 678 return ret; 679 680 off += cdns->pcm.num_out; 681 ret = intel_create_dai(cdns, dais, INTEL_PDI_BD, cdns->pcm.num_bd, 682 off, stream->num_ch_bd); 683 if (ret) 684 return ret; 685 686 return devm_snd_soc_register_component(cdns->dev, &dai_component, 687 dais, num_dai); 688 } 689 690 static void intel_program_sdi(struct sdw_intel *sdw, int dev_num) 691 { 692 int ret; 693 694 ret = hdac_bus_eml_sdw_set_lsdiid(sdw->link_res->hbus, sdw->instance, dev_num); 695 if (ret < 0) 696 dev_err(sdw->cdns.dev, "%s: could not set lsdiid for link %d %d\n", 697 __func__, sdw->instance, dev_num); 698 } 699 700 const struct sdw_intel_hw_ops sdw_intel_lnl_hw_ops = { 701 .debugfs_init = intel_ace2x_debugfs_init, 702 .debugfs_exit = intel_ace2x_debugfs_exit, 703 704 .register_dai = intel_register_dai, 705 706 .check_clock_stop = intel_check_clock_stop, 707 .start_bus = intel_start_bus, 708 .start_bus_after_reset = intel_start_bus_after_reset, 709 .start_bus_after_clock_stop = intel_start_bus_after_clock_stop, 710 .stop_bus = intel_stop_bus, 711 712 .link_power_up = intel_link_power_up, 713 .link_power_down = intel_link_power_down, 714 715 .shim_check_wake = intel_shim_check_wake, 716 .shim_wake = intel_shim_wake, 717 718 .pre_bank_switch = intel_pre_bank_switch, 719 .post_bank_switch = intel_post_bank_switch, 720 721 .sync_arm = intel_sync_arm, 722 .sync_go_unlocked = intel_sync_go_unlocked, 723 .sync_go = intel_sync_go, 724 .sync_check_cmdsync_unlocked = intel_check_cmdsync_unlocked, 725 726 .program_sdi = intel_program_sdi, 727 }; 728 EXPORT_SYMBOL_NS(sdw_intel_lnl_hw_ops, SOUNDWIRE_INTEL); 729 730 MODULE_IMPORT_NS(SND_SOC_SOF_HDA_MLINK); 731