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 struct snd_soc_dai *codec_dai) 114 { 115 const struct hda_dai_widget_dma_ops *ops = hda_dai_get_ops(substream, cpu_dai); 116 struct hdac_stream *hstream = &hext_stream->hstream; 117 struct hdac_bus *bus = hstream->bus; 118 struct sof_intel_hda_stream *hda_stream; 119 struct hdac_ext_link *hlink; 120 struct snd_sof_dev *sdev; 121 int stream_tag; 122 123 sdev = dai_to_sdev(substream, cpu_dai); 124 125 hlink = snd_hdac_ext_bus_get_hlink_by_name(bus, codec_dai->component->name); 126 if (!hlink) 127 return -EINVAL; 128 129 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { 130 stream_tag = hdac_stream(hext_stream)->stream_tag; 131 snd_hdac_ext_bus_link_clear_stream_id(hlink, stream_tag); 132 } 133 134 if (ops->release_hext_stream) 135 ops->release_hext_stream(sdev, cpu_dai, substream); 136 137 hext_stream->link_prepared = 0; 138 139 /* free the host DMA channel reserved by hostless streams */ 140 hda_stream = hstream_to_sof_hda_stream(hext_stream); 141 hda_stream->host_reserved = 0; 142 143 return 0; 144 } 145 146 static int hda_link_dma_hw_params(struct snd_pcm_substream *substream, 147 struct snd_pcm_hw_params *params, struct snd_soc_dai *cpu_dai) 148 { 149 const struct hda_dai_widget_dma_ops *ops = hda_dai_get_ops(substream, cpu_dai); 150 struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); 151 struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); 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 struct hdac_bus *bus; 157 unsigned int format_val; 158 unsigned int link_bps; 159 int stream_tag; 160 161 sdev = dai_to_sdev(substream, cpu_dai); 162 bus = sof_to_bus(sdev); 163 164 hlink = snd_hdac_ext_bus_get_hlink_by_name(bus, codec_dai->component->name); 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 snd_soc_dai_set_stream(codec_dai, hdac_stream(hext_stream), substream->stream); 186 187 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 188 link_bps = codec_dai->driver->playback.sig_bits; 189 else 190 link_bps = codec_dai->driver->capture.sig_bits; 191 192 if (ops->reset_hext_stream) 193 ops->reset_hext_stream(sdev, hext_stream); 194 195 format_val = snd_hdac_calc_stream_format(params_rate(params), params_channels(params), 196 params_format(params), link_bps, 0); 197 198 dev_dbg(bus->dev, "format_val=%#x, rate=%d, ch=%d, format=%d\n", format_val, 199 params_rate(params), params_channels(params), params_format(params)); 200 201 if (ops->setup_hext_stream) 202 ops->setup_hext_stream(sdev, hext_stream, format_val); 203 204 hext_stream->link_prepared = 1; 205 206 return 0; 207 } 208 209 static int __maybe_unused hda_dai_hw_free(struct snd_pcm_substream *substream, 210 struct snd_soc_dai *cpu_dai) 211 { 212 const struct hda_dai_widget_dma_ops *ops = hda_dai_get_ops(substream, cpu_dai); 213 struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); 214 struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); 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(sdev->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, codec_dai); 228 } 229 230 static int __maybe_unused hda_dai_hw_params(struct snd_pcm_substream *substream, 231 struct snd_pcm_hw_params *params, 232 struct snd_soc_dai *dai) 233 { 234 struct snd_soc_dapm_widget *w = snd_soc_dai_get_widget(dai, substream->stream); 235 const struct hda_dai_widget_dma_ops *ops = hda_dai_get_ops(substream, dai); 236 struct hdac_ext_stream *hext_stream; 237 struct snd_sof_dai_config_data data = { 0 }; 238 unsigned int flags = SOF_DAI_CONFIG_FLAGS_HW_PARAMS; 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 /* 264 * In contrast to IPC3, the dai trigger in IPC4 mixes pipeline state changes 265 * (over IPC channel) and DMA state change (direct host register changes). 266 */ 267 static int __maybe_unused hda_dai_trigger(struct snd_pcm_substream *substream, int cmd, 268 struct snd_soc_dai *dai) 269 { 270 const struct hda_dai_widget_dma_ops *ops = hda_dai_get_ops(substream, dai); 271 struct hdac_ext_stream *hext_stream; 272 struct snd_soc_pcm_runtime *rtd; 273 struct snd_soc_dai *codec_dai; 274 struct snd_sof_dev *sdev; 275 int ret; 276 277 dev_dbg(dai->dev, "cmd=%d dai %s direction %d\n", cmd, 278 dai->name, substream->stream); 279 280 sdev = dai_to_sdev(substream, dai); 281 282 hext_stream = ops->get_hext_stream(sdev, dai, substream); 283 if (!hext_stream) 284 return -EINVAL; 285 286 rtd = asoc_substream_to_rtd(substream); 287 codec_dai = asoc_rtd_to_codec(rtd, 0); 288 289 if (ops->pre_trigger) { 290 ret = ops->pre_trigger(sdev, dai, substream, cmd); 291 if (ret < 0) 292 return ret; 293 } 294 295 if (ops->trigger) { 296 ret = ops->trigger(sdev, dai, substream, cmd); 297 if (ret < 0) 298 return ret; 299 } 300 301 if (ops->post_trigger) { 302 ret = ops->post_trigger(sdev, dai, substream, cmd); 303 if (ret < 0) 304 return ret; 305 } 306 307 switch (cmd) { 308 case SNDRV_PCM_TRIGGER_SUSPEND: 309 ret = hda_link_dma_cleanup(substream, hext_stream, dai, codec_dai); 310 if (ret < 0) { 311 dev_err(sdev->dev, "%s: failed to clean up link DMA\n", __func__); 312 return ret; 313 } 314 break; 315 default: 316 break; 317 } 318 319 return 0; 320 } 321 322 #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_AUDIO_CODEC) 323 324 static int hda_dai_prepare(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) 325 { 326 struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); 327 int stream = substream->stream; 328 329 return hda_dai_hw_params(substream, &rtd->dpcm[stream].hw_params, dai); 330 } 331 332 static const struct snd_soc_dai_ops hda_dai_ops = { 333 .hw_params = hda_dai_hw_params, 334 .hw_free = hda_dai_hw_free, 335 .trigger = hda_dai_trigger, 336 .prepare = hda_dai_prepare, 337 }; 338 339 #endif 340 341 static int hda_dai_suspend(struct hdac_bus *bus) 342 { 343 struct snd_soc_pcm_runtime *rtd; 344 struct hdac_ext_stream *hext_stream; 345 struct hdac_stream *s; 346 int ret; 347 348 /* set internal flag for BE */ 349 list_for_each_entry(s, &bus->stream_list, list) { 350 351 hext_stream = stream_to_hdac_ext_stream(s); 352 353 /* 354 * clear stream. This should already be taken care for running 355 * streams when the SUSPEND trigger is called. But paused 356 * streams do not get suspended, so this needs to be done 357 * explicitly during suspend. 358 */ 359 if (hext_stream->link_substream) { 360 const struct hda_dai_widget_dma_ops *ops; 361 struct snd_sof_widget *swidget; 362 struct snd_soc_dapm_widget *w; 363 struct snd_soc_dai *codec_dai; 364 struct snd_soc_dai *cpu_dai; 365 struct snd_sof_dev *sdev; 366 struct snd_sof_dai *sdai; 367 368 rtd = asoc_substream_to_rtd(hext_stream->link_substream); 369 cpu_dai = asoc_rtd_to_cpu(rtd, 0); 370 codec_dai = asoc_rtd_to_codec(rtd, 0); 371 w = snd_soc_dai_get_widget(cpu_dai, hdac_stream(hext_stream)->direction); 372 swidget = w->dobj.private; 373 sdev = widget_to_sdev(w); 374 sdai = swidget->private; 375 ops = sdai->platform_private; 376 377 ret = hda_link_dma_cleanup(hext_stream->link_substream, 378 hext_stream, 379 cpu_dai, codec_dai); 380 if (ret < 0) 381 return ret; 382 383 /* for consistency with TRIGGER_SUSPEND */ 384 if (ops->post_trigger) { 385 ret = ops->post_trigger(sdev, cpu_dai, 386 hext_stream->link_substream, 387 SNDRV_PCM_TRIGGER_SUSPEND); 388 if (ret < 0) 389 return ret; 390 } 391 } 392 } 393 394 return 0; 395 } 396 397 #endif 398 399 void hda_set_dai_drv_ops(struct snd_sof_dev *sdev, struct snd_sof_dsp_ops *ops) 400 { 401 int i; 402 403 for (i = 0; i < ops->num_drv; i++) { 404 #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_AUDIO_CODEC) 405 if (strstr(ops->drv[i].name, "iDisp") || 406 strstr(ops->drv[i].name, "Analog") || 407 strstr(ops->drv[i].name, "Digital")) 408 ops->drv[i].ops = &hda_dai_ops; 409 #endif 410 } 411 412 if (sdev->pdata->ipc_type == SOF_INTEL_IPC4 && !hda_use_tplg_nhlt) { 413 struct sof_ipc4_fw_data *ipc4_data = sdev->private; 414 415 ipc4_data->nhlt = intel_nhlt_init(sdev->dev); 416 } 417 } 418 419 void hda_ops_free(struct snd_sof_dev *sdev) 420 { 421 if (sdev->pdata->ipc_type == SOF_INTEL_IPC4) { 422 struct sof_ipc4_fw_data *ipc4_data = sdev->private; 423 424 if (!hda_use_tplg_nhlt) 425 intel_nhlt_free(ipc4_data->nhlt); 426 } 427 } 428 EXPORT_SYMBOL_NS(hda_ops_free, SND_SOC_SOF_INTEL_HDA_COMMON); 429 430 /* 431 * common dai driver for skl+ platforms. 432 * some products who use this DAI array only physically have a subset of 433 * the DAIs, but no harm is done here by adding the whole set. 434 */ 435 struct snd_soc_dai_driver skl_dai[] = { 436 { 437 .name = "SSP0 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 = "SSP1 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 = "SSP2 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 = "SSP3 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 = "SSP4 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 = "SSP5 Pin", 493 .playback = { 494 .channels_min = 1, 495 .channels_max = 8, 496 }, 497 .capture = { 498 .channels_min = 1, 499 .channels_max = 8, 500 }, 501 }, 502 { 503 .name = "DMIC01 Pin", 504 .capture = { 505 .channels_min = 1, 506 .channels_max = 4, 507 }, 508 }, 509 { 510 .name = "DMIC16k Pin", 511 .capture = { 512 .channels_min = 1, 513 .channels_max = 4, 514 }, 515 }, 516 #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_AUDIO_CODEC) 517 { 518 .name = "iDisp1 Pin", 519 .playback = { 520 .channels_min = 1, 521 .channels_max = 8, 522 }, 523 }, 524 { 525 .name = "iDisp2 Pin", 526 .playback = { 527 .channels_min = 1, 528 .channels_max = 8, 529 }, 530 }, 531 { 532 .name = "iDisp3 Pin", 533 .playback = { 534 .channels_min = 1, 535 .channels_max = 8, 536 }, 537 }, 538 { 539 .name = "iDisp4 Pin", 540 .playback = { 541 .channels_min = 1, 542 .channels_max = 8, 543 }, 544 }, 545 { 546 .name = "Analog 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 = "Digital 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 { 568 .name = "Alt Analog CPU DAI", 569 .playback = { 570 .channels_min = 1, 571 .channels_max = 16, 572 }, 573 .capture = { 574 .channels_min = 1, 575 .channels_max = 16, 576 }, 577 }, 578 #endif 579 }; 580 581 int hda_dsp_dais_suspend(struct snd_sof_dev *sdev) 582 { 583 /* 584 * In the corner case where a SUSPEND happens during a PAUSE, the ALSA core 585 * does not throw the TRIGGER_SUSPEND. This leaves the DAIs in an unbalanced state. 586 * Since the component suspend is called last, we can trap this corner case 587 * and force the DAIs to release their resources. 588 */ 589 #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_LINK) 590 int ret; 591 592 ret = hda_dai_suspend(sof_to_bus(sdev)); 593 if (ret < 0) 594 return ret; 595 #endif 596 597 return 0; 598 } 599