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