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 case SNDRV_PCM_TRIGGER_STOP: 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 static const struct snd_soc_dai_ops hda_dai_ops = { 323 .hw_params = hda_dai_hw_params, 324 .hw_free = hda_dai_hw_free, 325 .trigger = hda_dai_trigger, 326 .prepare = hda_dai_prepare, 327 }; 328 329 static int hda_dai_suspend(struct hdac_bus *bus) 330 { 331 struct snd_soc_pcm_runtime *rtd; 332 struct hdac_ext_stream *hext_stream; 333 struct hdac_stream *s; 334 int ret; 335 336 /* set internal flag for BE */ 337 list_for_each_entry(s, &bus->stream_list, list) { 338 339 hext_stream = stream_to_hdac_ext_stream(s); 340 341 /* 342 * clear stream. This should already be taken care for running 343 * streams when the SUSPEND trigger is called. But paused 344 * streams do not get suspended, so this needs to be done 345 * explicitly during suspend. 346 */ 347 if (hext_stream->link_substream) { 348 const struct hda_dai_widget_dma_ops *ops; 349 struct snd_sof_widget *swidget; 350 struct snd_soc_dapm_widget *w; 351 struct snd_soc_dai *codec_dai; 352 struct snd_soc_dai *cpu_dai; 353 struct snd_sof_dev *sdev; 354 struct snd_sof_dai *sdai; 355 356 rtd = asoc_substream_to_rtd(hext_stream->link_substream); 357 cpu_dai = asoc_rtd_to_cpu(rtd, 0); 358 codec_dai = asoc_rtd_to_codec(rtd, 0); 359 w = snd_soc_dai_get_widget(cpu_dai, hdac_stream(hext_stream)->direction); 360 swidget = w->dobj.private; 361 sdev = snd_soc_component_get_drvdata(swidget->scomp); 362 sdai = swidget->private; 363 ops = sdai->platform_private; 364 365 ret = hda_link_dma_cleanup(hext_stream->link_substream, 366 hext_stream, 367 cpu_dai, codec_dai); 368 if (ret < 0) 369 return ret; 370 371 /* for consistency with TRIGGER_SUSPEND */ 372 if (ops->post_trigger) { 373 ret = ops->post_trigger(sdev, cpu_dai, 374 hext_stream->link_substream, 375 SNDRV_PCM_TRIGGER_SUSPEND); 376 if (ret < 0) 377 return ret; 378 } 379 } 380 } 381 382 return 0; 383 } 384 385 #endif 386 387 void hda_set_dai_drv_ops(struct snd_sof_dev *sdev, struct snd_sof_dsp_ops *ops) 388 { 389 int i; 390 391 for (i = 0; i < ops->num_drv; i++) { 392 #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_AUDIO_CODEC) 393 if (strstr(ops->drv[i].name, "iDisp") || 394 strstr(ops->drv[i].name, "Analog") || 395 strstr(ops->drv[i].name, "Digital")) 396 ops->drv[i].ops = &hda_dai_ops; 397 #endif 398 } 399 400 if (sdev->pdata->ipc_type == SOF_INTEL_IPC4 && !hda_use_tplg_nhlt) { 401 struct sof_ipc4_fw_data *ipc4_data = sdev->private; 402 403 ipc4_data->nhlt = intel_nhlt_init(sdev->dev); 404 } 405 } 406 407 void hda_ops_free(struct snd_sof_dev *sdev) 408 { 409 if (sdev->pdata->ipc_type == SOF_INTEL_IPC4) { 410 struct sof_ipc4_fw_data *ipc4_data = sdev->private; 411 412 if (!hda_use_tplg_nhlt) 413 intel_nhlt_free(ipc4_data->nhlt); 414 } 415 } 416 EXPORT_SYMBOL_NS(hda_ops_free, SND_SOC_SOF_INTEL_HDA_COMMON); 417 418 /* 419 * common dai driver for skl+ platforms. 420 * some products who use this DAI array only physically have a subset of 421 * the DAIs, but no harm is done here by adding the whole set. 422 */ 423 struct snd_soc_dai_driver skl_dai[] = { 424 { 425 .name = "SSP0 Pin", 426 .playback = { 427 .channels_min = 1, 428 .channels_max = 8, 429 }, 430 .capture = { 431 .channels_min = 1, 432 .channels_max = 8, 433 }, 434 }, 435 { 436 .name = "SSP1 Pin", 437 .playback = { 438 .channels_min = 1, 439 .channels_max = 8, 440 }, 441 .capture = { 442 .channels_min = 1, 443 .channels_max = 8, 444 }, 445 }, 446 { 447 .name = "SSP2 Pin", 448 .playback = { 449 .channels_min = 1, 450 .channels_max = 8, 451 }, 452 .capture = { 453 .channels_min = 1, 454 .channels_max = 8, 455 }, 456 }, 457 { 458 .name = "SSP3 Pin", 459 .playback = { 460 .channels_min = 1, 461 .channels_max = 8, 462 }, 463 .capture = { 464 .channels_min = 1, 465 .channels_max = 8, 466 }, 467 }, 468 { 469 .name = "SSP4 Pin", 470 .playback = { 471 .channels_min = 1, 472 .channels_max = 8, 473 }, 474 .capture = { 475 .channels_min = 1, 476 .channels_max = 8, 477 }, 478 }, 479 { 480 .name = "SSP5 Pin", 481 .playback = { 482 .channels_min = 1, 483 .channels_max = 8, 484 }, 485 .capture = { 486 .channels_min = 1, 487 .channels_max = 8, 488 }, 489 }, 490 { 491 .name = "DMIC01 Pin", 492 .capture = { 493 .channels_min = 1, 494 .channels_max = 4, 495 }, 496 }, 497 { 498 .name = "DMIC16k Pin", 499 .capture = { 500 .channels_min = 1, 501 .channels_max = 4, 502 }, 503 }, 504 #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_AUDIO_CODEC) 505 { 506 .name = "iDisp1 Pin", 507 .playback = { 508 .channels_min = 1, 509 .channels_max = 8, 510 }, 511 }, 512 { 513 .name = "iDisp2 Pin", 514 .playback = { 515 .channels_min = 1, 516 .channels_max = 8, 517 }, 518 }, 519 { 520 .name = "iDisp3 Pin", 521 .playback = { 522 .channels_min = 1, 523 .channels_max = 8, 524 }, 525 }, 526 { 527 .name = "iDisp4 Pin", 528 .playback = { 529 .channels_min = 1, 530 .channels_max = 8, 531 }, 532 }, 533 { 534 .name = "Analog CPU DAI", 535 .playback = { 536 .channels_min = 1, 537 .channels_max = 16, 538 }, 539 .capture = { 540 .channels_min = 1, 541 .channels_max = 16, 542 }, 543 }, 544 { 545 .name = "Digital CPU DAI", 546 .playback = { 547 .channels_min = 1, 548 .channels_max = 16, 549 }, 550 .capture = { 551 .channels_min = 1, 552 .channels_max = 16, 553 }, 554 }, 555 { 556 .name = "Alt Analog CPU DAI", 557 .playback = { 558 .channels_min = 1, 559 .channels_max = 16, 560 }, 561 .capture = { 562 .channels_min = 1, 563 .channels_max = 16, 564 }, 565 }, 566 #endif 567 }; 568 569 int hda_dsp_dais_suspend(struct snd_sof_dev *sdev) 570 { 571 /* 572 * In the corner case where a SUSPEND happens during a PAUSE, the ALSA core 573 * does not throw the TRIGGER_SUSPEND. This leaves the DAIs in an unbalanced state. 574 * Since the component suspend is called last, we can trap this corner case 575 * and force the DAIs to release their resources. 576 */ 577 #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_AUDIO_CODEC) 578 int ret; 579 580 ret = hda_dai_suspend(sof_to_bus(sdev)); 581 if (ret < 0) 582 return ret; 583 #endif 584 585 return 0; 586 } 587