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