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) 2018 Intel Corporation 7 // 8 // Authors: Keyon Jie <yang.jie@linux.intel.com> 9 // 10 11 #include <sound/pcm_params.h> 12 #include <sound/hdaudio_ext.h> 13 #include <sound/hda-mlink.h> 14 #include <sound/hda_register.h> 15 #include <sound/intel-nhlt.h> 16 #include <sound/sof/ipc4/header.h> 17 #include <uapi/sound/sof/header.h> 18 #include "../ipc4-priv.h" 19 #include "../ipc4-topology.h" 20 #include "../sof-priv.h" 21 #include "../sof-audio.h" 22 #include "hda.h" 23 24 /* 25 * The default method is to fetch NHLT from BIOS. With this parameter set 26 * it is possible to override that with NHLT in the SOF topology manifest. 27 */ 28 static bool hda_use_tplg_nhlt; 29 module_param_named(sof_use_tplg_nhlt, hda_use_tplg_nhlt, bool, 0444); 30 MODULE_PARM_DESC(sof_use_tplg_nhlt, "SOF topology nhlt override"); 31 32 int hda_dai_config(struct snd_soc_dapm_widget *w, unsigned int flags, 33 struct snd_sof_dai_config_data *data) 34 { 35 struct snd_sof_widget *swidget = w->dobj.private; 36 const struct sof_ipc_tplg_ops *tplg_ops; 37 struct snd_sof_dev *sdev; 38 int ret; 39 40 if (!swidget) 41 return 0; 42 43 sdev = widget_to_sdev(w); 44 tplg_ops = sof_ipc_get_ops(sdev, tplg); 45 46 if (tplg_ops && tplg_ops->dai_config) { 47 ret = tplg_ops->dai_config(sdev, swidget, flags, data); 48 if (ret < 0) { 49 dev_err(sdev->dev, "DAI config with flags %x failed for widget %s\n", 50 flags, w->name); 51 return ret; 52 } 53 } 54 55 return 0; 56 } 57 EXPORT_SYMBOL_NS(hda_dai_config, "SND_SOC_SOF_INTEL_HDA_COMMON"); 58 59 #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_LINK) 60 61 static struct snd_sof_dev *dai_to_sdev(struct snd_pcm_substream *substream, 62 struct snd_soc_dai *cpu_dai) 63 { 64 struct snd_soc_dapm_widget *w = snd_soc_dai_get_widget(cpu_dai, substream->stream); 65 66 return widget_to_sdev(w); 67 } 68 69 static const struct hda_dai_widget_dma_ops * 70 hda_dai_get_ops(struct snd_pcm_substream *substream, struct snd_soc_dai *cpu_dai) 71 { 72 struct snd_soc_dapm_widget *w = snd_soc_dai_get_widget(cpu_dai, substream->stream); 73 struct snd_sof_widget *swidget; 74 struct snd_sof_dev *sdev; 75 struct snd_sof_dai *sdai; 76 77 /* 78 * this is unlikely if the topology and the machine driver DAI links match. 79 * But if there's a missing DAI link in topology, this will prevent a NULL pointer 80 * dereference later on. 81 */ 82 if (!w) { 83 dev_err(cpu_dai->dev, "%s: widget is NULL\n", __func__); 84 return NULL; 85 } 86 87 sdev = widget_to_sdev(w); 88 swidget = w->dobj.private; 89 if (!swidget) { 90 dev_err(sdev->dev, "%s: swidget is NULL\n", __func__); 91 return NULL; 92 } 93 94 if (sdev->dspless_mode_selected) 95 return hda_select_dai_widget_ops(sdev, swidget); 96 97 sdai = swidget->private; 98 99 /* select and set the DAI widget ops if not set already */ 100 if (!sdai->platform_private) { 101 const struct hda_dai_widget_dma_ops *ops = 102 hda_select_dai_widget_ops(sdev, swidget); 103 if (!ops) 104 return NULL; 105 106 /* check if mandatory ops are set */ 107 if (!ops || !ops->get_hext_stream) 108 return NULL; 109 110 sdai->platform_private = ops; 111 } 112 113 return sdai->platform_private; 114 } 115 116 static int 117 hda_link_dma_cleanup(struct snd_pcm_substream *substream, 118 struct hdac_ext_stream *hext_stream, 119 struct snd_soc_dai *cpu_dai, bool release) 120 { 121 const struct hda_dai_widget_dma_ops *ops = hda_dai_get_ops(substream, cpu_dai); 122 struct sof_intel_hda_stream *hda_stream; 123 struct hdac_ext_link *hlink; 124 struct snd_sof_dev *sdev; 125 int stream_tag; 126 127 if (!ops) { 128 dev_err(cpu_dai->dev, "DAI widget ops not set\n"); 129 return -EINVAL; 130 } 131 132 sdev = dai_to_sdev(substream, cpu_dai); 133 134 hlink = ops->get_hlink(sdev, substream); 135 if (!hlink) 136 return -EINVAL; 137 138 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { 139 stream_tag = hdac_stream(hext_stream)->stream_tag; 140 snd_hdac_ext_bus_link_clear_stream_id(hlink, stream_tag); 141 } 142 143 if (!release) { 144 /* 145 * Force stream reconfiguration without releasing the channel on 146 * subsequent stream restart (without free), including LinkDMA 147 * reset. 148 * The stream is released via hda_dai_hw_free() 149 */ 150 hext_stream->link_prepared = 0; 151 return 0; 152 } 153 154 if (ops->release_hext_stream) 155 ops->release_hext_stream(sdev, cpu_dai, substream); 156 157 hext_stream->link_prepared = 0; 158 159 /* free the host DMA channel reserved by hostless streams */ 160 hda_stream = hstream_to_sof_hda_stream(hext_stream); 161 hda_stream->host_reserved = 0; 162 163 return 0; 164 } 165 166 static int hda_link_dma_hw_params(struct snd_pcm_substream *substream, 167 struct snd_pcm_hw_params *params, struct snd_soc_dai *cpu_dai) 168 { 169 const struct hda_dai_widget_dma_ops *ops = hda_dai_get_ops(substream, cpu_dai); 170 struct hdac_ext_stream *hext_stream; 171 struct hdac_stream *hstream; 172 struct hdac_ext_link *hlink; 173 struct snd_sof_dev *sdev; 174 int stream_tag; 175 176 if (!ops) { 177 dev_err(cpu_dai->dev, "DAI widget ops not set\n"); 178 return -EINVAL; 179 } 180 181 sdev = dai_to_sdev(substream, cpu_dai); 182 183 hlink = ops->get_hlink(sdev, substream); 184 if (!hlink) 185 return -EINVAL; 186 187 hext_stream = ops->get_hext_stream(sdev, cpu_dai, substream); 188 189 if (!hext_stream) { 190 if (ops->assign_hext_stream) 191 hext_stream = ops->assign_hext_stream(sdev, cpu_dai, substream); 192 } 193 194 if (!hext_stream) 195 return -EBUSY; 196 197 hstream = &hext_stream->hstream; 198 stream_tag = hstream->stream_tag; 199 200 if (hext_stream->hstream.direction == SNDRV_PCM_STREAM_PLAYBACK) 201 snd_hdac_ext_bus_link_set_stream_id(hlink, stream_tag); 202 203 /* set the hdac_stream in the codec dai */ 204 if (ops->codec_dai_set_stream) 205 ops->codec_dai_set_stream(sdev, substream, hstream); 206 207 if (ops->reset_hext_stream) 208 ops->reset_hext_stream(sdev, hext_stream); 209 210 if (ops->calc_stream_format && ops->setup_hext_stream) { 211 unsigned int format_val = ops->calc_stream_format(sdev, substream, params); 212 213 ops->setup_hext_stream(sdev, hext_stream, format_val); 214 } 215 216 hext_stream->link_prepared = 1; 217 218 return 0; 219 } 220 221 static int __maybe_unused hda_dai_hw_free(struct snd_pcm_substream *substream, 222 struct snd_soc_dai *cpu_dai) 223 { 224 const struct hda_dai_widget_dma_ops *ops = hda_dai_get_ops(substream, cpu_dai); 225 struct hdac_ext_stream *hext_stream; 226 struct snd_sof_dev *sdev = dai_to_sdev(substream, cpu_dai); 227 228 if (!ops) { 229 dev_err(cpu_dai->dev, "DAI widget ops not set\n"); 230 return -EINVAL; 231 } 232 233 hext_stream = ops->get_hext_stream(sdev, cpu_dai, substream); 234 if (!hext_stream) 235 return 0; 236 237 return hda_link_dma_cleanup(substream, hext_stream, cpu_dai, true); 238 } 239 240 static int __maybe_unused hda_dai_hw_params_data(struct snd_pcm_substream *substream, 241 struct snd_pcm_hw_params *params, 242 struct snd_soc_dai *dai, 243 struct snd_sof_dai_config_data *data, 244 unsigned int flags) 245 { 246 struct snd_soc_dapm_widget *w = snd_soc_dai_get_widget(dai, substream->stream); 247 const struct hda_dai_widget_dma_ops *ops = hda_dai_get_ops(substream, dai); 248 struct hdac_ext_stream *hext_stream; 249 struct snd_sof_dev *sdev = widget_to_sdev(w); 250 int ret; 251 252 if (!ops) { 253 dev_err(sdev->dev, "DAI widget ops not set\n"); 254 return -EINVAL; 255 } 256 257 hext_stream = ops->get_hext_stream(sdev, dai, substream); 258 if (hext_stream && hext_stream->link_prepared) 259 return 0; 260 261 ret = hda_link_dma_hw_params(substream, params, dai); 262 if (ret < 0) 263 return ret; 264 265 hext_stream = ops->get_hext_stream(sdev, dai, substream); 266 267 flags |= SOF_DAI_CONFIG_FLAGS_2_STEP_STOP << SOF_DAI_CONFIG_FLAGS_QUIRK_SHIFT; 268 data->dai_data = hdac_stream(hext_stream)->stream_tag - 1; 269 270 return hda_dai_config(w, flags, data); 271 } 272 273 static int __maybe_unused hda_dai_hw_params(struct snd_pcm_substream *substream, 274 struct snd_pcm_hw_params *params, 275 struct snd_soc_dai *dai) 276 { 277 struct snd_sof_dai_config_data data = { 0 }; 278 unsigned int flags = SOF_DAI_CONFIG_FLAGS_HW_PARAMS; 279 280 return hda_dai_hw_params_data(substream, params, dai, &data, flags); 281 } 282 283 /* 284 * In contrast to IPC3, the dai trigger in IPC4 mixes pipeline state changes 285 * (over IPC channel) and DMA state change (direct host register changes). 286 */ 287 static int __maybe_unused hda_dai_trigger(struct snd_pcm_substream *substream, int cmd, 288 struct snd_soc_dai *dai) 289 { 290 const struct hda_dai_widget_dma_ops *ops = hda_dai_get_ops(substream, dai); 291 struct hdac_ext_stream *hext_stream; 292 struct snd_sof_dev *sdev; 293 int ret; 294 295 if (!ops) { 296 dev_err(dai->dev, "DAI widget ops not set\n"); 297 return -EINVAL; 298 } 299 300 dev_dbg(dai->dev, "cmd=%d dai %s direction %d\n", cmd, 301 dai->name, substream->stream); 302 303 sdev = dai_to_sdev(substream, dai); 304 305 hext_stream = ops->get_hext_stream(sdev, dai, substream); 306 if (!hext_stream) 307 return -EINVAL; 308 309 if (ops->pre_trigger) { 310 ret = ops->pre_trigger(sdev, dai, substream, cmd); 311 if (ret < 0) 312 return ret; 313 } 314 315 if (ops->trigger) { 316 ret = ops->trigger(sdev, dai, substream, cmd); 317 if (ret < 0) 318 return ret; 319 } 320 321 if (ops->post_trigger) { 322 ret = ops->post_trigger(sdev, dai, substream, cmd); 323 if (ret < 0) 324 return ret; 325 } 326 327 switch (cmd) { 328 case SNDRV_PCM_TRIGGER_STOP: 329 case SNDRV_PCM_TRIGGER_SUSPEND: 330 ret = hda_link_dma_cleanup(substream, hext_stream, dai, 331 cmd != SNDRV_PCM_TRIGGER_STOP); 332 if (ret < 0) { 333 dev_err(sdev->dev, "%s: failed to clean up link DMA\n", __func__); 334 return ret; 335 } 336 break; 337 default: 338 break; 339 } 340 341 return 0; 342 } 343 344 #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_AUDIO_CODEC) 345 346 static int hda_dai_prepare(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) 347 { 348 struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); 349 int stream = substream->stream; 350 351 return hda_dai_hw_params(substream, &rtd->dpcm[stream].hw_params, dai); 352 } 353 354 static const struct snd_soc_dai_ops hda_dai_ops = { 355 .hw_params = hda_dai_hw_params, 356 .hw_free = hda_dai_hw_free, 357 .trigger = hda_dai_trigger, 358 .prepare = hda_dai_prepare, 359 }; 360 361 #endif 362 363 static struct sof_ipc4_copier *widget_to_copier(struct snd_soc_dapm_widget *w) 364 { 365 struct snd_sof_widget *swidget = w->dobj.private; 366 struct snd_sof_dai *sdai = swidget->private; 367 struct sof_ipc4_copier *ipc4_copier = (struct sof_ipc4_copier *)sdai->private; 368 369 return ipc4_copier; 370 } 371 372 static int non_hda_dai_hw_params_data(struct snd_pcm_substream *substream, 373 struct snd_pcm_hw_params *params, 374 struct snd_soc_dai *cpu_dai, 375 struct snd_sof_dai_config_data *data, 376 unsigned int flags) 377 { 378 struct snd_soc_dapm_widget *w = snd_soc_dai_get_widget(cpu_dai, substream->stream); 379 struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); 380 struct sof_ipc4_dma_config_tlv *dma_config_tlv; 381 const struct hda_dai_widget_dma_ops *ops; 382 struct sof_ipc4_dma_config *dma_config; 383 struct sof_ipc4_copier *ipc4_copier; 384 struct hdac_ext_stream *hext_stream; 385 struct hdac_stream *hstream; 386 struct snd_sof_dev *sdev; 387 struct snd_soc_dai *dai; 388 int cpu_dai_id; 389 int stream_id; 390 int ret; 391 392 ops = hda_dai_get_ops(substream, cpu_dai); 393 if (!ops) { 394 dev_err(cpu_dai->dev, "DAI widget ops not set\n"); 395 return -EINVAL; 396 } 397 398 sdev = widget_to_sdev(w); 399 hext_stream = ops->get_hext_stream(sdev, cpu_dai, substream); 400 401 /* nothing more to do if the link is already prepared */ 402 if (hext_stream && hext_stream->link_prepared) 403 return 0; 404 405 /* use HDaudio stream handling */ 406 ret = hda_dai_hw_params_data(substream, params, cpu_dai, data, flags); 407 if (ret < 0) { 408 dev_err(cpu_dai->dev, "%s: hda_dai_hw_params_data failed: %d\n", __func__, ret); 409 return ret; 410 } 411 412 if (sdev->dspless_mode_selected) 413 return 0; 414 415 /* get stream_id */ 416 hext_stream = ops->get_hext_stream(sdev, cpu_dai, substream); 417 418 if (!hext_stream) { 419 dev_err(cpu_dai->dev, "%s: no hext_stream found\n", __func__); 420 return -ENODEV; 421 } 422 423 hstream = &hext_stream->hstream; 424 stream_id = hstream->stream_tag; 425 426 if (!stream_id) { 427 dev_err(cpu_dai->dev, "%s: no stream_id allocated\n", __func__); 428 return -ENODEV; 429 } 430 431 /* configure TLV */ 432 ipc4_copier = widget_to_copier(w); 433 434 for_each_rtd_cpu_dais(rtd, cpu_dai_id, dai) { 435 if (dai == cpu_dai) 436 break; 437 } 438 439 dma_config_tlv = &ipc4_copier->dma_config_tlv[cpu_dai_id]; 440 dma_config_tlv->type = SOF_IPC4_GTW_DMA_CONFIG_ID; 441 /* dma_config_priv_size is zero */ 442 dma_config_tlv->length = sizeof(dma_config_tlv->dma_config); 443 444 dma_config = &dma_config_tlv->dma_config; 445 446 dma_config->dma_method = SOF_IPC4_DMA_METHOD_HDA; 447 dma_config->pre_allocated_by_host = 1; 448 dma_config->dma_channel_id = stream_id - 1; 449 dma_config->stream_id = stream_id; 450 /* 451 * Currently we use a DMA for each device in ALH blob. The device will 452 * be copied in sof_ipc4_prepare_copier_module. 453 */ 454 dma_config->dma_stream_channel_map.device_count = 1; 455 dma_config->dma_priv_config_size = 0; 456 457 return 0; 458 } 459 460 static int non_hda_dai_hw_params(struct snd_pcm_substream *substream, 461 struct snd_pcm_hw_params *params, 462 struct snd_soc_dai *cpu_dai) 463 { 464 struct snd_sof_dai_config_data data = { 0 }; 465 unsigned int flags = SOF_DAI_CONFIG_FLAGS_HW_PARAMS; 466 467 return non_hda_dai_hw_params_data(substream, params, cpu_dai, &data, flags); 468 } 469 470 static int non_hda_dai_prepare(struct snd_pcm_substream *substream, 471 struct snd_soc_dai *cpu_dai) 472 { 473 struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); 474 int stream = substream->stream; 475 476 return non_hda_dai_hw_params(substream, &rtd->dpcm[stream].hw_params, cpu_dai); 477 } 478 479 static const struct snd_soc_dai_ops ssp_dai_ops = { 480 .hw_params = non_hda_dai_hw_params, 481 .hw_free = hda_dai_hw_free, 482 .trigger = hda_dai_trigger, 483 .prepare = non_hda_dai_prepare, 484 }; 485 486 static const struct snd_soc_dai_ops dmic_dai_ops = { 487 .hw_params = non_hda_dai_hw_params, 488 .hw_free = hda_dai_hw_free, 489 .trigger = hda_dai_trigger, 490 .prepare = non_hda_dai_prepare, 491 }; 492 493 int sdw_hda_dai_hw_params(struct snd_pcm_substream *substream, 494 struct snd_pcm_hw_params *params, 495 struct snd_soc_dai *cpu_dai, 496 int link_id, 497 int intel_alh_id) 498 { 499 struct snd_soc_dapm_widget *w = snd_soc_dai_get_widget(cpu_dai, substream->stream); 500 struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); 501 struct sof_ipc4_dma_config_tlv *dma_config_tlv; 502 struct snd_sof_dai_config_data data = { 0 }; 503 unsigned int flags = SOF_DAI_CONFIG_FLAGS_HW_PARAMS; 504 const struct hda_dai_widget_dma_ops *ops; 505 struct sof_ipc4_dma_config *dma_config; 506 struct sof_ipc4_copier *ipc4_copier; 507 struct hdac_ext_stream *hext_stream; 508 struct snd_soc_dai *dai; 509 struct snd_sof_dev *sdev; 510 bool cpu_dai_found = false; 511 int cpu_dai_id; 512 int ch_mask; 513 int ret; 514 int i; 515 516 if (!w) { 517 dev_err(cpu_dai->dev, "%s widget not found, check amp link num in the topology\n", 518 cpu_dai->name); 519 return -EINVAL; 520 } 521 522 ops = hda_dai_get_ops(substream, cpu_dai); 523 if (!ops) { 524 dev_err(cpu_dai->dev, "DAI widget ops not set\n"); 525 return -EINVAL; 526 } 527 528 sdev = widget_to_sdev(w); 529 hext_stream = ops->get_hext_stream(sdev, cpu_dai, substream); 530 531 /* nothing more to do if the link is already prepared */ 532 if (hext_stream && hext_stream->link_prepared) 533 return 0; 534 535 /* 536 * reset the PCMSyCM registers to handle a prepare callback when the PCM is restarted 537 * due to xruns or after a call to snd_pcm_drain/drop() 538 */ 539 ret = hdac_bus_eml_sdw_map_stream_ch(sof_to_bus(sdev), link_id, cpu_dai->id, 540 0, 0, substream->stream); 541 if (ret < 0) { 542 dev_err(cpu_dai->dev, "%s: hdac_bus_eml_sdw_map_stream_ch failed %d\n", 543 __func__, ret); 544 return ret; 545 } 546 547 data.dai_index = (link_id << 8) | cpu_dai->id; 548 data.dai_node_id = intel_alh_id; 549 ret = non_hda_dai_hw_params_data(substream, params, cpu_dai, &data, flags); 550 if (ret < 0) { 551 dev_err(cpu_dai->dev, "%s: non_hda_dai_hw_params failed %d\n", __func__, ret); 552 return ret; 553 } 554 555 hext_stream = ops->get_hext_stream(sdev, cpu_dai, substream); 556 if (!hext_stream) 557 return -ENODEV; 558 559 /* 560 * in the case of SoundWire we need to program the PCMSyCM registers. In case 561 * of aggregated devices, we need to define the channel mask for each sublink 562 * by reconstructing the split done in soc-pcm.c 563 */ 564 for_each_rtd_cpu_dais(rtd, cpu_dai_id, dai) { 565 if (dai == cpu_dai) { 566 cpu_dai_found = true; 567 break; 568 } 569 } 570 571 if (!cpu_dai_found) 572 return -ENODEV; 573 574 ch_mask = GENMASK(params_channels(params) - 1, 0); 575 576 ret = hdac_bus_eml_sdw_map_stream_ch(sof_to_bus(sdev), link_id, cpu_dai->id, 577 ch_mask, 578 hdac_stream(hext_stream)->stream_tag, 579 substream->stream); 580 if (ret < 0) { 581 dev_err(cpu_dai->dev, "%s: hdac_bus_eml_sdw_map_stream_ch failed %d\n", 582 __func__, ret); 583 return ret; 584 } 585 586 if (sdev->dspless_mode_selected) 587 return 0; 588 589 ipc4_copier = widget_to_copier(w); 590 dma_config_tlv = &ipc4_copier->dma_config_tlv[cpu_dai_id]; 591 dma_config = &dma_config_tlv->dma_config; 592 dma_config->dma_stream_channel_map.mapping[0].device = data.dai_index; 593 dma_config->dma_stream_channel_map.mapping[0].channel_mask = ch_mask; 594 595 /* 596 * copy the dma_config_tlv to all ipc4_copier in the same link. Because only one copier 597 * will be handled in sof_ipc4_prepare_copier_module. 598 */ 599 for_each_rtd_cpu_dais(rtd, i, dai) { 600 w = snd_soc_dai_get_widget(dai, substream->stream); 601 if (!w) { 602 dev_err(cpu_dai->dev, 603 "%s widget not found, check amp link num in the topology\n", 604 dai->name); 605 return -EINVAL; 606 } 607 ipc4_copier = widget_to_copier(w); 608 memcpy(&ipc4_copier->dma_config_tlv[cpu_dai_id], dma_config_tlv, 609 sizeof(*dma_config_tlv)); 610 } 611 return 0; 612 } 613 EXPORT_SYMBOL_NS(sdw_hda_dai_hw_params, "SND_SOC_SOF_INTEL_HDA_COMMON"); 614 615 int sdw_hda_dai_hw_free(struct snd_pcm_substream *substream, 616 struct snd_soc_dai *cpu_dai, 617 int link_id) 618 { 619 struct snd_soc_dapm_widget *w = snd_soc_dai_get_widget(cpu_dai, substream->stream); 620 struct snd_sof_dev *sdev; 621 int ret; 622 623 ret = hda_dai_hw_free(substream, cpu_dai); 624 if (ret < 0) { 625 dev_err(cpu_dai->dev, "%s: non_hda_dai_hw_free failed %d\n", __func__, ret); 626 return ret; 627 } 628 629 sdev = widget_to_sdev(w); 630 631 /* in the case of SoundWire we need to reset the PCMSyCM registers */ 632 ret = hdac_bus_eml_sdw_map_stream_ch(sof_to_bus(sdev), link_id, cpu_dai->id, 633 0, 0, substream->stream); 634 if (ret < 0) { 635 dev_err(cpu_dai->dev, "%s: hdac_bus_eml_sdw_map_stream_ch failed %d\n", 636 __func__, ret); 637 return ret; 638 } 639 640 return 0; 641 } 642 EXPORT_SYMBOL_NS(sdw_hda_dai_hw_free, "SND_SOC_SOF_INTEL_HDA_COMMON"); 643 644 int sdw_hda_dai_trigger(struct snd_pcm_substream *substream, int cmd, 645 struct snd_soc_dai *cpu_dai) 646 { 647 return hda_dai_trigger(substream, cmd, cpu_dai); 648 } 649 EXPORT_SYMBOL_NS(sdw_hda_dai_trigger, "SND_SOC_SOF_INTEL_HDA_COMMON"); 650 651 static int hda_dai_suspend(struct hdac_bus *bus) 652 { 653 struct snd_soc_pcm_runtime *rtd; 654 struct hdac_ext_stream *hext_stream; 655 struct hdac_stream *s; 656 int ret; 657 658 /* set internal flag for BE */ 659 list_for_each_entry(s, &bus->stream_list, list) { 660 661 hext_stream = stream_to_hdac_ext_stream(s); 662 663 /* 664 * clear stream. This should already be taken care for running 665 * streams when the SUSPEND trigger is called. But paused 666 * streams do not get suspended, so this needs to be done 667 * explicitly during suspend. 668 */ 669 if (hext_stream->link_substream) { 670 const struct hda_dai_widget_dma_ops *ops; 671 struct snd_sof_widget *swidget; 672 struct snd_soc_dapm_widget *w; 673 struct snd_soc_dai *cpu_dai; 674 struct snd_sof_dev *sdev; 675 struct snd_sof_dai *sdai; 676 677 rtd = snd_soc_substream_to_rtd(hext_stream->link_substream); 678 cpu_dai = snd_soc_rtd_to_cpu(rtd, 0); 679 w = snd_soc_dai_get_widget(cpu_dai, hdac_stream(hext_stream)->direction); 680 swidget = w->dobj.private; 681 sdev = widget_to_sdev(w); 682 sdai = swidget->private; 683 ops = sdai->platform_private; 684 685 if (rtd->dpcm[hext_stream->link_substream->stream].state != 686 SND_SOC_DPCM_STATE_PAUSED) 687 continue; 688 689 /* for consistency with TRIGGER_SUSPEND */ 690 if (ops->post_trigger) { 691 ret = ops->post_trigger(sdev, cpu_dai, 692 hext_stream->link_substream, 693 SNDRV_PCM_TRIGGER_SUSPEND); 694 if (ret < 0) 695 return ret; 696 } 697 698 ret = hda_link_dma_cleanup(hext_stream->link_substream, 699 hext_stream, cpu_dai, true); 700 if (ret < 0) 701 return ret; 702 } 703 } 704 705 return 0; 706 } 707 708 static void ssp_set_dai_drv_ops(struct snd_sof_dev *sdev, struct snd_sof_dsp_ops *ops) 709 { 710 const struct sof_intel_dsp_desc *chip; 711 int i; 712 713 chip = get_chip_info(sdev->pdata); 714 715 if (chip->hw_ip_version >= SOF_INTEL_ACE_2_0) { 716 for (i = 0; i < ops->num_drv; i++) { 717 if (strstr(ops->drv[i].name, "SSP")) 718 ops->drv[i].ops = &ssp_dai_ops; 719 } 720 } 721 } 722 723 static void dmic_set_dai_drv_ops(struct snd_sof_dev *sdev, struct snd_sof_dsp_ops *ops) 724 { 725 const struct sof_intel_dsp_desc *chip; 726 int i; 727 728 chip = get_chip_info(sdev->pdata); 729 730 if (chip->hw_ip_version >= SOF_INTEL_ACE_2_0) { 731 for (i = 0; i < ops->num_drv; i++) { 732 if (strstr(ops->drv[i].name, "DMIC")) 733 ops->drv[i].ops = &dmic_dai_ops; 734 } 735 } 736 } 737 738 #else 739 740 static inline void ssp_set_dai_drv_ops(struct snd_sof_dev *sdev, struct snd_sof_dsp_ops *ops) {} 741 static inline void dmic_set_dai_drv_ops(struct snd_sof_dev *sdev, struct snd_sof_dsp_ops *ops) {} 742 743 #endif /* CONFIG_SND_SOC_SOF_HDA_LINK */ 744 745 void hda_set_dai_drv_ops(struct snd_sof_dev *sdev, struct snd_sof_dsp_ops *ops) 746 { 747 int i; 748 749 for (i = 0; i < ops->num_drv; i++) { 750 #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_AUDIO_CODEC) 751 if (strstr(ops->drv[i].name, "iDisp") || 752 strstr(ops->drv[i].name, "Analog") || 753 strstr(ops->drv[i].name, "Digital")) 754 ops->drv[i].ops = &hda_dai_ops; 755 #endif 756 } 757 758 ssp_set_dai_drv_ops(sdev, ops); 759 dmic_set_dai_drv_ops(sdev, ops); 760 761 if (sdev->pdata->ipc_type == SOF_IPC_TYPE_4 && !hda_use_tplg_nhlt) { 762 struct sof_ipc4_fw_data *ipc4_data = sdev->private; 763 764 ipc4_data->nhlt = intel_nhlt_init(sdev->dev); 765 } 766 } 767 EXPORT_SYMBOL_NS(hda_set_dai_drv_ops, "SND_SOC_SOF_INTEL_HDA_COMMON"); 768 769 void hda_ops_free(struct snd_sof_dev *sdev) 770 { 771 if (sdev->pdata->ipc_type == SOF_IPC_TYPE_4) { 772 struct sof_ipc4_fw_data *ipc4_data = sdev->private; 773 774 if (!hda_use_tplg_nhlt) 775 intel_nhlt_free(ipc4_data->nhlt); 776 777 kfree(sdev->private); 778 sdev->private = NULL; 779 } 780 } 781 EXPORT_SYMBOL_NS(hda_ops_free, "SND_SOC_SOF_INTEL_HDA_COMMON"); 782 783 /* 784 * common dai driver for skl+ platforms. 785 * some products who use this DAI array only physically have a subset of 786 * the DAIs, but no harm is done here by adding the whole set. 787 */ 788 struct snd_soc_dai_driver skl_dai[] = { 789 { 790 .name = "SSP0 Pin", 791 .playback = { 792 .channels_min = 1, 793 .channels_max = 8, 794 }, 795 .capture = { 796 .channels_min = 1, 797 .channels_max = 8, 798 }, 799 }, 800 { 801 .name = "SSP1 Pin", 802 .playback = { 803 .channels_min = 1, 804 .channels_max = 8, 805 }, 806 .capture = { 807 .channels_min = 1, 808 .channels_max = 8, 809 }, 810 }, 811 { 812 .name = "SSP2 Pin", 813 .playback = { 814 .channels_min = 1, 815 .channels_max = 8, 816 }, 817 .capture = { 818 .channels_min = 1, 819 .channels_max = 8, 820 }, 821 }, 822 { 823 .name = "SSP3 Pin", 824 .playback = { 825 .channels_min = 1, 826 .channels_max = 8, 827 }, 828 .capture = { 829 .channels_min = 1, 830 .channels_max = 8, 831 }, 832 }, 833 { 834 .name = "SSP4 Pin", 835 .playback = { 836 .channels_min = 1, 837 .channels_max = 8, 838 }, 839 .capture = { 840 .channels_min = 1, 841 .channels_max = 8, 842 }, 843 }, 844 { 845 .name = "SSP5 Pin", 846 .playback = { 847 .channels_min = 1, 848 .channels_max = 8, 849 }, 850 .capture = { 851 .channels_min = 1, 852 .channels_max = 8, 853 }, 854 }, 855 { 856 .name = "DMIC01 Pin", 857 .capture = { 858 .channels_min = 1, 859 .channels_max = 4, 860 }, 861 }, 862 { 863 .name = "DMIC16k Pin", 864 .capture = { 865 .channels_min = 1, 866 .channels_max = 4, 867 }, 868 }, 869 { 870 /* Virtual CPU DAI for Echo reference */ 871 .name = "Loopback Virtual Pin", 872 .capture = { 873 .channels_min = 1, 874 .channels_max = 2, 875 }, 876 }, 877 #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_AUDIO_CODEC) 878 { 879 .name = "iDisp1 Pin", 880 .playback = { 881 .channels_min = 1, 882 .channels_max = 8, 883 }, 884 }, 885 { 886 .name = "iDisp2 Pin", 887 .playback = { 888 .channels_min = 1, 889 .channels_max = 8, 890 }, 891 }, 892 { 893 .name = "iDisp3 Pin", 894 .playback = { 895 .channels_min = 1, 896 .channels_max = 8, 897 }, 898 }, 899 { 900 .name = "iDisp4 Pin", 901 .playback = { 902 .channels_min = 1, 903 .channels_max = 8, 904 }, 905 }, 906 { 907 .name = "Analog CPU DAI", 908 .playback = { 909 .channels_min = 1, 910 .channels_max = 16, 911 }, 912 .capture = { 913 .channels_min = 1, 914 .channels_max = 16, 915 }, 916 }, 917 { 918 .name = "Digital CPU DAI", 919 .playback = { 920 .channels_min = 1, 921 .channels_max = 16, 922 }, 923 .capture = { 924 .channels_min = 1, 925 .channels_max = 16, 926 }, 927 }, 928 { 929 .name = "Alt Analog CPU DAI", 930 .playback = { 931 .channels_min = 1, 932 .channels_max = 16, 933 }, 934 .capture = { 935 .channels_min = 1, 936 .channels_max = 16, 937 }, 938 }, 939 #endif 940 }; 941 EXPORT_SYMBOL_NS(skl_dai, "SND_SOC_SOF_INTEL_HDA_COMMON"); 942 943 int hda_dsp_dais_suspend(struct snd_sof_dev *sdev) 944 { 945 /* 946 * In the corner case where a SUSPEND happens during a PAUSE, the ALSA core 947 * does not throw the TRIGGER_SUSPEND. This leaves the DAIs in an unbalanced state. 948 * Since the component suspend is called last, we can trap this corner case 949 * and force the DAIs to release their resources. 950 */ 951 #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_LINK) 952 int ret; 953 954 ret = hda_dai_suspend(sof_to_bus(sdev)); 955 if (ret < 0) 956 return ret; 957 #endif 958 959 return 0; 960 } 961