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