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