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 ? false : true); 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 ops = hda_dai_get_ops(substream, cpu_dai); 507 if (!ops) { 508 dev_err(cpu_dai->dev, "DAI widget ops not set\n"); 509 return -EINVAL; 510 } 511 512 sdev = widget_to_sdev(w); 513 hext_stream = ops->get_hext_stream(sdev, cpu_dai, substream); 514 515 /* nothing more to do if the link is already prepared */ 516 if (hext_stream && hext_stream->link_prepared) 517 return 0; 518 519 /* 520 * reset the PCMSyCM registers to handle a prepare callback when the PCM is restarted 521 * due to xruns or after a call to snd_pcm_drain/drop() 522 */ 523 ret = hdac_bus_eml_sdw_map_stream_ch(sof_to_bus(sdev), link_id, cpu_dai->id, 524 0, 0, substream->stream); 525 if (ret < 0) { 526 dev_err(cpu_dai->dev, "%s: hdac_bus_eml_sdw_map_stream_ch failed %d\n", 527 __func__, ret); 528 return ret; 529 } 530 531 data.dai_index = (link_id << 8) | cpu_dai->id; 532 data.dai_node_id = intel_alh_id; 533 ret = non_hda_dai_hw_params_data(substream, params, cpu_dai, &data, flags); 534 if (ret < 0) { 535 dev_err(cpu_dai->dev, "%s: non_hda_dai_hw_params failed %d\n", __func__, ret); 536 return ret; 537 } 538 539 hext_stream = ops->get_hext_stream(sdev, cpu_dai, substream); 540 if (!hext_stream) 541 return -ENODEV; 542 543 /* 544 * in the case of SoundWire we need to program the PCMSyCM registers. In case 545 * of aggregated devices, we need to define the channel mask for each sublink 546 * by reconstructing the split done in soc-pcm.c 547 */ 548 for_each_rtd_cpu_dais(rtd, cpu_dai_id, dai) { 549 if (dai == cpu_dai) { 550 cpu_dai_found = true; 551 break; 552 } 553 } 554 555 if (!cpu_dai_found) 556 return -ENODEV; 557 558 ch_mask = GENMASK(params_channels(params) - 1, 0); 559 560 ret = hdac_bus_eml_sdw_map_stream_ch(sof_to_bus(sdev), link_id, cpu_dai->id, 561 ch_mask, 562 hdac_stream(hext_stream)->stream_tag, 563 substream->stream); 564 if (ret < 0) { 565 dev_err(cpu_dai->dev, "%s: hdac_bus_eml_sdw_map_stream_ch failed %d\n", 566 __func__, ret); 567 return ret; 568 } 569 570 if (sdev->dspless_mode_selected) 571 return 0; 572 573 ipc4_copier = widget_to_copier(w); 574 dma_config_tlv = &ipc4_copier->dma_config_tlv[cpu_dai_id]; 575 dma_config = &dma_config_tlv->dma_config; 576 dma_config->dma_stream_channel_map.mapping[0].device = data.dai_index; 577 dma_config->dma_stream_channel_map.mapping[0].channel_mask = ch_mask; 578 579 /* 580 * copy the dma_config_tlv to all ipc4_copier in the same link. Because only one copier 581 * will be handled in sof_ipc4_prepare_copier_module. 582 */ 583 for_each_rtd_cpu_dais(rtd, i, dai) { 584 w = snd_soc_dai_get_widget(dai, substream->stream); 585 ipc4_copier = widget_to_copier(w); 586 memcpy(&ipc4_copier->dma_config_tlv[cpu_dai_id], dma_config_tlv, 587 sizeof(*dma_config_tlv)); 588 } 589 return 0; 590 } 591 EXPORT_SYMBOL_NS(sdw_hda_dai_hw_params, "SND_SOC_SOF_INTEL_HDA_COMMON"); 592 593 int sdw_hda_dai_hw_free(struct snd_pcm_substream *substream, 594 struct snd_soc_dai *cpu_dai, 595 int link_id) 596 { 597 struct snd_soc_dapm_widget *w = snd_soc_dai_get_widget(cpu_dai, substream->stream); 598 struct snd_sof_dev *sdev; 599 int ret; 600 601 ret = hda_dai_hw_free(substream, cpu_dai); 602 if (ret < 0) { 603 dev_err(cpu_dai->dev, "%s: non_hda_dai_hw_free failed %d\n", __func__, ret); 604 return ret; 605 } 606 607 sdev = widget_to_sdev(w); 608 609 /* in the case of SoundWire we need to reset the PCMSyCM registers */ 610 ret = hdac_bus_eml_sdw_map_stream_ch(sof_to_bus(sdev), link_id, cpu_dai->id, 611 0, 0, substream->stream); 612 if (ret < 0) { 613 dev_err(cpu_dai->dev, "%s: hdac_bus_eml_sdw_map_stream_ch failed %d\n", 614 __func__, ret); 615 return ret; 616 } 617 618 return 0; 619 } 620 EXPORT_SYMBOL_NS(sdw_hda_dai_hw_free, "SND_SOC_SOF_INTEL_HDA_COMMON"); 621 622 int sdw_hda_dai_trigger(struct snd_pcm_substream *substream, int cmd, 623 struct snd_soc_dai *cpu_dai) 624 { 625 return hda_dai_trigger(substream, cmd, cpu_dai); 626 } 627 EXPORT_SYMBOL_NS(sdw_hda_dai_trigger, "SND_SOC_SOF_INTEL_HDA_COMMON"); 628 629 static int hda_dai_suspend(struct hdac_bus *bus) 630 { 631 struct snd_soc_pcm_runtime *rtd; 632 struct hdac_ext_stream *hext_stream; 633 struct hdac_stream *s; 634 int ret; 635 636 /* set internal flag for BE */ 637 list_for_each_entry(s, &bus->stream_list, list) { 638 639 hext_stream = stream_to_hdac_ext_stream(s); 640 641 /* 642 * clear stream. This should already be taken care for running 643 * streams when the SUSPEND trigger is called. But paused 644 * streams do not get suspended, so this needs to be done 645 * explicitly during suspend. 646 */ 647 if (hext_stream->link_substream) { 648 const struct hda_dai_widget_dma_ops *ops; 649 struct snd_sof_widget *swidget; 650 struct snd_soc_dapm_widget *w; 651 struct snd_soc_dai *cpu_dai; 652 struct snd_sof_dev *sdev; 653 struct snd_sof_dai *sdai; 654 655 rtd = snd_soc_substream_to_rtd(hext_stream->link_substream); 656 cpu_dai = snd_soc_rtd_to_cpu(rtd, 0); 657 w = snd_soc_dai_get_widget(cpu_dai, hdac_stream(hext_stream)->direction); 658 swidget = w->dobj.private; 659 sdev = widget_to_sdev(w); 660 sdai = swidget->private; 661 ops = sdai->platform_private; 662 663 if (rtd->dpcm[hext_stream->link_substream->stream].state != 664 SND_SOC_DPCM_STATE_PAUSED) 665 continue; 666 667 /* for consistency with TRIGGER_SUSPEND */ 668 if (ops->post_trigger) { 669 ret = ops->post_trigger(sdev, cpu_dai, 670 hext_stream->link_substream, 671 SNDRV_PCM_TRIGGER_SUSPEND); 672 if (ret < 0) 673 return ret; 674 } 675 676 ret = hda_link_dma_cleanup(hext_stream->link_substream, 677 hext_stream, cpu_dai, true); 678 if (ret < 0) 679 return ret; 680 } 681 } 682 683 return 0; 684 } 685 686 static void ssp_set_dai_drv_ops(struct snd_sof_dev *sdev, struct snd_sof_dsp_ops *ops) 687 { 688 const struct sof_intel_dsp_desc *chip; 689 int i; 690 691 chip = get_chip_info(sdev->pdata); 692 693 if (chip->hw_ip_version >= SOF_INTEL_ACE_2_0) { 694 for (i = 0; i < ops->num_drv; i++) { 695 if (strstr(ops->drv[i].name, "SSP")) 696 ops->drv[i].ops = &ssp_dai_ops; 697 } 698 } 699 } 700 701 static void dmic_set_dai_drv_ops(struct snd_sof_dev *sdev, struct snd_sof_dsp_ops *ops) 702 { 703 const struct sof_intel_dsp_desc *chip; 704 int i; 705 706 chip = get_chip_info(sdev->pdata); 707 708 if (chip->hw_ip_version >= SOF_INTEL_ACE_2_0) { 709 for (i = 0; i < ops->num_drv; i++) { 710 if (strstr(ops->drv[i].name, "DMIC")) 711 ops->drv[i].ops = &dmic_dai_ops; 712 } 713 } 714 } 715 716 #else 717 718 static inline void ssp_set_dai_drv_ops(struct snd_sof_dev *sdev, struct snd_sof_dsp_ops *ops) {} 719 static inline void dmic_set_dai_drv_ops(struct snd_sof_dev *sdev, struct snd_sof_dsp_ops *ops) {} 720 721 #endif /* CONFIG_SND_SOC_SOF_HDA_LINK */ 722 723 void hda_set_dai_drv_ops(struct snd_sof_dev *sdev, struct snd_sof_dsp_ops *ops) 724 { 725 int i; 726 727 for (i = 0; i < ops->num_drv; i++) { 728 #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_AUDIO_CODEC) 729 if (strstr(ops->drv[i].name, "iDisp") || 730 strstr(ops->drv[i].name, "Analog") || 731 strstr(ops->drv[i].name, "Digital")) 732 ops->drv[i].ops = &hda_dai_ops; 733 #endif 734 } 735 736 ssp_set_dai_drv_ops(sdev, ops); 737 dmic_set_dai_drv_ops(sdev, ops); 738 739 if (sdev->pdata->ipc_type == SOF_IPC_TYPE_4 && !hda_use_tplg_nhlt) { 740 struct sof_ipc4_fw_data *ipc4_data = sdev->private; 741 742 ipc4_data->nhlt = intel_nhlt_init(sdev->dev); 743 } 744 } 745 EXPORT_SYMBOL_NS(hda_set_dai_drv_ops, "SND_SOC_SOF_INTEL_HDA_COMMON"); 746 747 void hda_ops_free(struct snd_sof_dev *sdev) 748 { 749 if (sdev->pdata->ipc_type == SOF_IPC_TYPE_4) { 750 struct sof_ipc4_fw_data *ipc4_data = sdev->private; 751 752 if (!hda_use_tplg_nhlt) 753 intel_nhlt_free(ipc4_data->nhlt); 754 755 kfree(sdev->private); 756 sdev->private = NULL; 757 } 758 } 759 EXPORT_SYMBOL_NS(hda_ops_free, "SND_SOC_SOF_INTEL_HDA_COMMON"); 760 761 /* 762 * common dai driver for skl+ platforms. 763 * some products who use this DAI array only physically have a subset of 764 * the DAIs, but no harm is done here by adding the whole set. 765 */ 766 struct snd_soc_dai_driver skl_dai[] = { 767 { 768 .name = "SSP0 Pin", 769 .playback = { 770 .channels_min = 1, 771 .channels_max = 8, 772 }, 773 .capture = { 774 .channels_min = 1, 775 .channels_max = 8, 776 }, 777 }, 778 { 779 .name = "SSP1 Pin", 780 .playback = { 781 .channels_min = 1, 782 .channels_max = 8, 783 }, 784 .capture = { 785 .channels_min = 1, 786 .channels_max = 8, 787 }, 788 }, 789 { 790 .name = "SSP2 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 = "SSP3 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 = "SSP4 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 = "SSP5 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 = "DMIC01 Pin", 835 .capture = { 836 .channels_min = 1, 837 .channels_max = 4, 838 }, 839 }, 840 { 841 .name = "DMIC16k Pin", 842 .capture = { 843 .channels_min = 1, 844 .channels_max = 4, 845 }, 846 }, 847 #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_AUDIO_CODEC) 848 { 849 .name = "iDisp1 Pin", 850 .playback = { 851 .channels_min = 1, 852 .channels_max = 8, 853 }, 854 }, 855 { 856 .name = "iDisp2 Pin", 857 .playback = { 858 .channels_min = 1, 859 .channels_max = 8, 860 }, 861 }, 862 { 863 .name = "iDisp3 Pin", 864 .playback = { 865 .channels_min = 1, 866 .channels_max = 8, 867 }, 868 }, 869 { 870 .name = "iDisp4 Pin", 871 .playback = { 872 .channels_min = 1, 873 .channels_max = 8, 874 }, 875 }, 876 { 877 .name = "Analog CPU DAI", 878 .playback = { 879 .channels_min = 1, 880 .channels_max = 16, 881 }, 882 .capture = { 883 .channels_min = 1, 884 .channels_max = 16, 885 }, 886 }, 887 { 888 .name = "Digital CPU DAI", 889 .playback = { 890 .channels_min = 1, 891 .channels_max = 16, 892 }, 893 .capture = { 894 .channels_min = 1, 895 .channels_max = 16, 896 }, 897 }, 898 { 899 .name = "Alt Analog CPU DAI", 900 .playback = { 901 .channels_min = 1, 902 .channels_max = 16, 903 }, 904 .capture = { 905 .channels_min = 1, 906 .channels_max = 16, 907 }, 908 }, 909 #endif 910 }; 911 EXPORT_SYMBOL_NS(skl_dai, "SND_SOC_SOF_INTEL_HDA_COMMON"); 912 913 int hda_dsp_dais_suspend(struct snd_sof_dev *sdev) 914 { 915 /* 916 * In the corner case where a SUSPEND happens during a PAUSE, the ALSA core 917 * does not throw the TRIGGER_SUSPEND. This leaves the DAIs in an unbalanced state. 918 * Since the component suspend is called last, we can trap this corner case 919 * and force the DAIs to release their resources. 920 */ 921 #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_LINK) 922 int ret; 923 924 ret = hda_dai_suspend(sof_to_bus(sdev)); 925 if (ret < 0) 926 return ret; 927 #endif 928 929 return 0; 930 } 931