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. All rights reserved. 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/intel-nhlt.h> 14 #include <sound/sof/ipc4/header.h> 15 #include <uapi/sound/sof/header.h> 16 #include "../ipc4-priv.h" 17 #include "../ipc4-topology.h" 18 #include "../sof-priv.h" 19 #include "../sof-audio.h" 20 #include "hda.h" 21 22 /* 23 * The default method is to fetch NHLT from BIOS. With this parameter set 24 * it is possible to override that with NHLT in the SOF topology manifest. 25 */ 26 static bool hda_use_tplg_nhlt; 27 module_param_named(sof_use_tplg_nhlt, hda_use_tplg_nhlt, bool, 0444); 28 MODULE_PARM_DESC(sof_use_tplg_nhlt, "SOF topology nhlt override"); 29 30 static struct snd_sof_dev *widget_to_sdev(struct snd_soc_dapm_widget *w) 31 { 32 struct snd_sof_widget *swidget = w->dobj.private; 33 struct snd_soc_component *component = swidget->scomp; 34 35 return snd_soc_component_get_drvdata(component); 36 } 37 38 int hda_dai_config(struct snd_soc_dapm_widget *w, unsigned int flags, 39 struct snd_sof_dai_config_data *data) 40 { 41 struct snd_sof_widget *swidget = w->dobj.private; 42 const struct sof_ipc_tplg_ops *tplg_ops; 43 struct snd_sof_dev *sdev; 44 int ret; 45 46 if (!swidget) 47 return 0; 48 49 sdev = widget_to_sdev(w); 50 tplg_ops = sof_ipc_get_ops(sdev, tplg); 51 52 if (tplg_ops && tplg_ops->dai_config) { 53 ret = tplg_ops->dai_config(sdev, swidget, flags, data); 54 if (ret < 0) { 55 dev_err(sdev->dev, "DAI config with flags %x failed for widget %s\n", 56 flags, w->name); 57 return ret; 58 } 59 } 60 61 return 0; 62 } 63 64 #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_LINK) 65 66 static struct snd_sof_dev *dai_to_sdev(struct snd_pcm_substream *substream, 67 struct snd_soc_dai *cpu_dai) 68 { 69 struct snd_soc_dapm_widget *w = snd_soc_dai_get_widget(cpu_dai, substream->stream); 70 71 return widget_to_sdev(w); 72 } 73 74 static const struct hda_dai_widget_dma_ops * 75 hda_dai_get_ops(struct snd_pcm_substream *substream, struct snd_soc_dai *cpu_dai) 76 { 77 struct snd_soc_dapm_widget *w = snd_soc_dai_get_widget(cpu_dai, substream->stream); 78 struct snd_sof_widget *swidget = w->dobj.private; 79 struct snd_sof_dev *sdev; 80 struct snd_sof_dai *sdai; 81 82 sdev = widget_to_sdev(w); 83 84 /* 85 * The swidget parameter of hda_select_dai_widget_ops() is ignored in 86 * case of DSPless mode 87 */ 88 if (sdev->dspless_mode_selected) 89 return hda_select_dai_widget_ops(sdev, NULL); 90 91 sdai = swidget->private; 92 93 /* select and set the DAI widget ops if not set already */ 94 if (!sdai->platform_private) { 95 const struct hda_dai_widget_dma_ops *ops = 96 hda_select_dai_widget_ops(sdev, swidget); 97 if (!ops) 98 return NULL; 99 100 /* check if mandatory ops are set */ 101 if (!ops || !ops->get_hext_stream) 102 return NULL; 103 104 sdai->platform_private = ops; 105 } 106 107 return sdai->platform_private; 108 } 109 110 static int hda_link_dma_cleanup(struct snd_pcm_substream *substream, 111 struct hdac_ext_stream *hext_stream, 112 struct snd_soc_dai *cpu_dai) 113 { 114 const struct hda_dai_widget_dma_ops *ops = hda_dai_get_ops(substream, cpu_dai); 115 struct sof_intel_hda_stream *hda_stream; 116 struct hdac_ext_link *hlink; 117 struct snd_sof_dev *sdev; 118 int stream_tag; 119 120 if (!ops) { 121 dev_err(cpu_dai->dev, "DAI widget ops not set\n"); 122 return -EINVAL; 123 } 124 125 sdev = dai_to_sdev(substream, cpu_dai); 126 127 hlink = ops->get_hlink(sdev, substream); 128 if (!hlink) 129 return -EINVAL; 130 131 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { 132 stream_tag = hdac_stream(hext_stream)->stream_tag; 133 snd_hdac_ext_bus_link_clear_stream_id(hlink, stream_tag); 134 } 135 136 if (ops->release_hext_stream) 137 ops->release_hext_stream(sdev, cpu_dai, substream); 138 139 hext_stream->link_prepared = 0; 140 141 /* free the host DMA channel reserved by hostless streams */ 142 hda_stream = hstream_to_sof_hda_stream(hext_stream); 143 hda_stream->host_reserved = 0; 144 145 return 0; 146 } 147 148 static int hda_link_dma_hw_params(struct snd_pcm_substream *substream, 149 struct snd_pcm_hw_params *params, struct snd_soc_dai *cpu_dai) 150 { 151 const struct hda_dai_widget_dma_ops *ops = hda_dai_get_ops(substream, cpu_dai); 152 struct hdac_ext_stream *hext_stream; 153 struct hdac_stream *hstream; 154 struct hdac_ext_link *hlink; 155 struct snd_sof_dev *sdev; 156 int stream_tag; 157 158 if (!ops) { 159 dev_err(cpu_dai->dev, "DAI widget ops not set\n"); 160 return -EINVAL; 161 } 162 163 sdev = dai_to_sdev(substream, cpu_dai); 164 165 hlink = ops->get_hlink(sdev, substream); 166 if (!hlink) 167 return -EINVAL; 168 169 hext_stream = ops->get_hext_stream(sdev, cpu_dai, substream); 170 171 if (!hext_stream) { 172 if (ops->assign_hext_stream) 173 hext_stream = ops->assign_hext_stream(sdev, cpu_dai, substream); 174 } 175 176 if (!hext_stream) 177 return -EBUSY; 178 179 hstream = &hext_stream->hstream; 180 stream_tag = hstream->stream_tag; 181 182 if (hext_stream->hstream.direction == SNDRV_PCM_STREAM_PLAYBACK) 183 snd_hdac_ext_bus_link_set_stream_id(hlink, stream_tag); 184 185 /* set the hdac_stream in the codec dai */ 186 if (ops->codec_dai_set_stream) 187 ops->codec_dai_set_stream(sdev, substream, hstream); 188 189 if (ops->reset_hext_stream) 190 ops->reset_hext_stream(sdev, hext_stream); 191 192 if (ops->calc_stream_format && ops->setup_hext_stream) { 193 unsigned int format_val = ops->calc_stream_format(sdev, substream, params); 194 195 ops->setup_hext_stream(sdev, hext_stream, format_val); 196 } 197 198 hext_stream->link_prepared = 1; 199 200 return 0; 201 } 202 203 static int __maybe_unused hda_dai_hw_free(struct snd_pcm_substream *substream, 204 struct snd_soc_dai *cpu_dai) 205 { 206 const struct hda_dai_widget_dma_ops *ops = hda_dai_get_ops(substream, cpu_dai); 207 struct hdac_ext_stream *hext_stream; 208 struct snd_sof_dev *sdev = dai_to_sdev(substream, cpu_dai); 209 210 if (!ops) { 211 dev_err(cpu_dai->dev, "DAI widget ops not set\n"); 212 return -EINVAL; 213 } 214 215 hext_stream = ops->get_hext_stream(sdev, cpu_dai, substream); 216 if (!hext_stream) 217 return 0; 218 219 return hda_link_dma_cleanup(substream, hext_stream, cpu_dai); 220 } 221 222 static int __maybe_unused hda_dai_hw_params(struct snd_pcm_substream *substream, 223 struct snd_pcm_hw_params *params, 224 struct snd_soc_dai *dai) 225 { 226 struct snd_soc_dapm_widget *w = snd_soc_dai_get_widget(dai, substream->stream); 227 const struct hda_dai_widget_dma_ops *ops = hda_dai_get_ops(substream, dai); 228 struct hdac_ext_stream *hext_stream; 229 struct snd_sof_dai_config_data data = { 0 }; 230 unsigned int flags = SOF_DAI_CONFIG_FLAGS_HW_PARAMS; 231 struct snd_sof_dev *sdev = widget_to_sdev(w); 232 int ret; 233 234 if (!ops) { 235 dev_err(sdev->dev, "DAI widget ops not set\n"); 236 return -EINVAL; 237 } 238 239 hext_stream = ops->get_hext_stream(sdev, dai, substream); 240 if (hext_stream && hext_stream->link_prepared) 241 return 0; 242 243 ret = hda_link_dma_hw_params(substream, params, dai); 244 if (ret < 0) 245 return ret; 246 247 hext_stream = ops->get_hext_stream(sdev, dai, substream); 248 249 flags |= SOF_DAI_CONFIG_FLAGS_2_STEP_STOP << SOF_DAI_CONFIG_FLAGS_QUIRK_SHIFT; 250 data.dai_data = hdac_stream(hext_stream)->stream_tag - 1; 251 252 return hda_dai_config(w, flags, &data); 253 } 254 255 /* 256 * In contrast to IPC3, the dai trigger in IPC4 mixes pipeline state changes 257 * (over IPC channel) and DMA state change (direct host register changes). 258 */ 259 static int __maybe_unused hda_dai_trigger(struct snd_pcm_substream *substream, int cmd, 260 struct snd_soc_dai *dai) 261 { 262 const struct hda_dai_widget_dma_ops *ops = hda_dai_get_ops(substream, dai); 263 struct hdac_ext_stream *hext_stream; 264 struct snd_sof_dev *sdev; 265 int ret; 266 267 if (!ops) { 268 dev_err(dai->dev, "DAI widget ops not set\n"); 269 return -EINVAL; 270 } 271 272 dev_dbg(dai->dev, "cmd=%d dai %s direction %d\n", cmd, 273 dai->name, substream->stream); 274 275 sdev = dai_to_sdev(substream, dai); 276 277 hext_stream = ops->get_hext_stream(sdev, dai, substream); 278 if (!hext_stream) 279 return -EINVAL; 280 281 if (ops->pre_trigger) { 282 ret = ops->pre_trigger(sdev, dai, substream, cmd); 283 if (ret < 0) 284 return ret; 285 } 286 287 if (ops->trigger) { 288 ret = ops->trigger(sdev, dai, substream, cmd); 289 if (ret < 0) 290 return ret; 291 } 292 293 if (ops->post_trigger) { 294 ret = ops->post_trigger(sdev, dai, substream, cmd); 295 if (ret < 0) 296 return ret; 297 } 298 299 switch (cmd) { 300 case SNDRV_PCM_TRIGGER_SUSPEND: 301 ret = hda_link_dma_cleanup(substream, hext_stream, dai); 302 if (ret < 0) { 303 dev_err(sdev->dev, "%s: failed to clean up link DMA\n", __func__); 304 return ret; 305 } 306 break; 307 default: 308 break; 309 } 310 311 return 0; 312 } 313 314 #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_AUDIO_CODEC) 315 316 static int hda_dai_prepare(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) 317 { 318 struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); 319 int stream = substream->stream; 320 321 return hda_dai_hw_params(substream, &rtd->dpcm[stream].hw_params, dai); 322 } 323 324 static const struct snd_soc_dai_ops hda_dai_ops = { 325 .hw_params = hda_dai_hw_params, 326 .hw_free = hda_dai_hw_free, 327 .trigger = hda_dai_trigger, 328 .prepare = hda_dai_prepare, 329 }; 330 331 #endif 332 333 static int hda_dai_suspend(struct hdac_bus *bus) 334 { 335 struct snd_soc_pcm_runtime *rtd; 336 struct hdac_ext_stream *hext_stream; 337 struct hdac_stream *s; 338 int ret; 339 340 /* set internal flag for BE */ 341 list_for_each_entry(s, &bus->stream_list, list) { 342 343 hext_stream = stream_to_hdac_ext_stream(s); 344 345 /* 346 * clear stream. This should already be taken care for running 347 * streams when the SUSPEND trigger is called. But paused 348 * streams do not get suspended, so this needs to be done 349 * explicitly during suspend. 350 */ 351 if (hext_stream->link_substream) { 352 const struct hda_dai_widget_dma_ops *ops; 353 struct snd_sof_widget *swidget; 354 struct snd_soc_dapm_widget *w; 355 struct snd_soc_dai *cpu_dai; 356 struct snd_sof_dev *sdev; 357 struct snd_sof_dai *sdai; 358 359 rtd = asoc_substream_to_rtd(hext_stream->link_substream); 360 cpu_dai = asoc_rtd_to_cpu(rtd, 0); 361 w = snd_soc_dai_get_widget(cpu_dai, hdac_stream(hext_stream)->direction); 362 swidget = w->dobj.private; 363 sdev = widget_to_sdev(w); 364 sdai = swidget->private; 365 ops = sdai->platform_private; 366 367 ret = hda_link_dma_cleanup(hext_stream->link_substream, 368 hext_stream, 369 cpu_dai); 370 if (ret < 0) 371 return ret; 372 373 /* for consistency with TRIGGER_SUSPEND */ 374 if (ops->post_trigger) { 375 ret = ops->post_trigger(sdev, cpu_dai, 376 hext_stream->link_substream, 377 SNDRV_PCM_TRIGGER_SUSPEND); 378 if (ret < 0) 379 return ret; 380 } 381 } 382 } 383 384 return 0; 385 } 386 387 #endif 388 389 void hda_set_dai_drv_ops(struct snd_sof_dev *sdev, struct snd_sof_dsp_ops *ops) 390 { 391 int i; 392 393 for (i = 0; i < ops->num_drv; i++) { 394 #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_AUDIO_CODEC) 395 if (strstr(ops->drv[i].name, "iDisp") || 396 strstr(ops->drv[i].name, "Analog") || 397 strstr(ops->drv[i].name, "Digital")) 398 ops->drv[i].ops = &hda_dai_ops; 399 #endif 400 } 401 402 if (sdev->pdata->ipc_type == SOF_INTEL_IPC4 && !hda_use_tplg_nhlt) { 403 struct sof_ipc4_fw_data *ipc4_data = sdev->private; 404 405 ipc4_data->nhlt = intel_nhlt_init(sdev->dev); 406 } 407 } 408 409 void hda_ops_free(struct snd_sof_dev *sdev) 410 { 411 if (sdev->pdata->ipc_type == SOF_INTEL_IPC4) { 412 struct sof_ipc4_fw_data *ipc4_data = sdev->private; 413 414 if (!hda_use_tplg_nhlt) 415 intel_nhlt_free(ipc4_data->nhlt); 416 } 417 } 418 EXPORT_SYMBOL_NS(hda_ops_free, SND_SOC_SOF_INTEL_HDA_COMMON); 419 420 /* 421 * common dai driver for skl+ platforms. 422 * some products who use this DAI array only physically have a subset of 423 * the DAIs, but no harm is done here by adding the whole set. 424 */ 425 struct snd_soc_dai_driver skl_dai[] = { 426 { 427 .name = "SSP0 Pin", 428 .playback = { 429 .channels_min = 1, 430 .channels_max = 8, 431 }, 432 .capture = { 433 .channels_min = 1, 434 .channels_max = 8, 435 }, 436 }, 437 { 438 .name = "SSP1 Pin", 439 .playback = { 440 .channels_min = 1, 441 .channels_max = 8, 442 }, 443 .capture = { 444 .channels_min = 1, 445 .channels_max = 8, 446 }, 447 }, 448 { 449 .name = "SSP2 Pin", 450 .playback = { 451 .channels_min = 1, 452 .channels_max = 8, 453 }, 454 .capture = { 455 .channels_min = 1, 456 .channels_max = 8, 457 }, 458 }, 459 { 460 .name = "SSP3 Pin", 461 .playback = { 462 .channels_min = 1, 463 .channels_max = 8, 464 }, 465 .capture = { 466 .channels_min = 1, 467 .channels_max = 8, 468 }, 469 }, 470 { 471 .name = "SSP4 Pin", 472 .playback = { 473 .channels_min = 1, 474 .channels_max = 8, 475 }, 476 .capture = { 477 .channels_min = 1, 478 .channels_max = 8, 479 }, 480 }, 481 { 482 .name = "SSP5 Pin", 483 .playback = { 484 .channels_min = 1, 485 .channels_max = 8, 486 }, 487 .capture = { 488 .channels_min = 1, 489 .channels_max = 8, 490 }, 491 }, 492 { 493 .name = "DMIC01 Pin", 494 .capture = { 495 .channels_min = 1, 496 .channels_max = 4, 497 }, 498 }, 499 { 500 .name = "DMIC16k Pin", 501 .capture = { 502 .channels_min = 1, 503 .channels_max = 4, 504 }, 505 }, 506 #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_AUDIO_CODEC) 507 { 508 .name = "iDisp1 Pin", 509 .playback = { 510 .channels_min = 1, 511 .channels_max = 8, 512 }, 513 }, 514 { 515 .name = "iDisp2 Pin", 516 .playback = { 517 .channels_min = 1, 518 .channels_max = 8, 519 }, 520 }, 521 { 522 .name = "iDisp3 Pin", 523 .playback = { 524 .channels_min = 1, 525 .channels_max = 8, 526 }, 527 }, 528 { 529 .name = "iDisp4 Pin", 530 .playback = { 531 .channels_min = 1, 532 .channels_max = 8, 533 }, 534 }, 535 { 536 .name = "Analog CPU DAI", 537 .playback = { 538 .channels_min = 1, 539 .channels_max = 16, 540 }, 541 .capture = { 542 .channels_min = 1, 543 .channels_max = 16, 544 }, 545 }, 546 { 547 .name = "Digital CPU DAI", 548 .playback = { 549 .channels_min = 1, 550 .channels_max = 16, 551 }, 552 .capture = { 553 .channels_min = 1, 554 .channels_max = 16, 555 }, 556 }, 557 { 558 .name = "Alt Analog CPU DAI", 559 .playback = { 560 .channels_min = 1, 561 .channels_max = 16, 562 }, 563 .capture = { 564 .channels_min = 1, 565 .channels_max = 16, 566 }, 567 }, 568 #endif 569 }; 570 571 int hda_dsp_dais_suspend(struct snd_sof_dev *sdev) 572 { 573 /* 574 * In the corner case where a SUSPEND happens during a PAUSE, the ALSA core 575 * does not throw the TRIGGER_SUSPEND. This leaves the DAIs in an unbalanced state. 576 * Since the component suspend is called last, we can trap this corner case 577 * and force the DAIs to release their resources. 578 */ 579 #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_LINK) 580 int ret; 581 582 ret = hda_dai_suspend(sof_to_bus(sdev)); 583 if (ret < 0) 584 return ret; 585 #endif 586 587 return 0; 588 } 589