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) 2022 Intel Corporation 7 8 #include <sound/pcm_params.h> 9 #include <sound/hdaudio_ext.h> 10 #include <sound/hda_register.h> 11 #include <sound/hda-mlink.h> 12 #include <sound/sof/ipc4/header.h> 13 #include <uapi/sound/sof/header.h> 14 #include "../ipc4-priv.h" 15 #include "../ipc4-topology.h" 16 #include "../sof-priv.h" 17 #include "../sof-audio.h" 18 #include "hda.h" 19 20 /* These ops are only applicable for the HDA DAI's in their current form */ 21 #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_LINK) 22 /* 23 * This function checks if the host DMA stream corresponding 24 * to the link DMA stream_tag argument is assigned to one 25 * of the FEs connected to the BE DAI. 26 */ 27 static bool hda_check_fes(struct snd_soc_pcm_runtime *rtd, 28 int dir, int stream_tag) 29 { 30 struct snd_pcm_substream *fe_substream; 31 struct hdac_stream *fe_hstream; 32 struct snd_soc_dpcm *dpcm; 33 34 for_each_dpcm_fe(rtd, dir, dpcm) { 35 fe_substream = snd_soc_dpcm_get_substream(dpcm->fe, dir); 36 fe_hstream = fe_substream->runtime->private_data; 37 if (fe_hstream->stream_tag == stream_tag) 38 return true; 39 } 40 41 return false; 42 } 43 44 static struct hdac_ext_stream * 45 hda_link_stream_assign(struct hdac_bus *bus, struct snd_pcm_substream *substream, 46 enum hda_bus_ml_link_type link_type) 47 { 48 struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); 49 struct sof_intel_hda_dev *sof_hda = bus_to_sof_hda(bus); 50 struct sof_intel_hda_stream *hda_stream; 51 const struct sof_intel_dsp_desc *chip; 52 struct snd_sof_dev *sdev; 53 struct hdac_ext_stream *res = NULL; 54 struct hdac_stream *hstream = NULL; 55 int stream_dir = substream->stream; 56 bool is_multi = link_type == HDA_BUS_ML_LINK_HDA || link_type == HDA_BUS_ML_LINK_UAOL; 57 bool is_play = stream_dir == SNDRV_PCM_STREAM_PLAYBACK; 58 bool is_sdw = link_type == HDA_BUS_ML_LINK_SDW; 59 bool is_hda = link_type == HDA_BUS_ML_LINK_HDA; 60 u32 concur_block_mask = 0; 61 u32 seq_block_mask = 0; 62 unsigned int stream_idx; 63 64 if (!bus->ppcap) { 65 dev_err(bus->dev, "stream type not supported\n"); 66 return NULL; 67 } 68 69 /* 70 * On ACE2+ the link DMA stream allocator must avoid two HW errata, 71 * see the comment on struct sof_intel_hda_dev. 72 * 73 * - Concurrent cross-direction: SoundWire conflicts with HDA, iDisp 74 * and UAOL on the same physical stream index; SSP and DMIC are safe. 75 * - Sequential playback: a stream index previously used by an HDA/iDisp 76 * link cannot drive any non-HDA/iDisp link in the same direction 77 * until the next controller reset. 78 * 79 * The masks are protected by bus->reg_lock; sample them inside the 80 * lock together with the stream walk to keep the decision atomic 81 * with concurrent allocations and releases. 82 */ 83 guard(spinlock_irq)(&bus->reg_lock); 84 85 if (is_sdw) 86 concur_block_mask = sof_hda->link_dma_active_multi_mask[!stream_dir]; 87 else if (is_multi) 88 concur_block_mask = sof_hda->link_dma_active_sdw_mask[!stream_dir]; 89 if (is_play && !is_hda) 90 seq_block_mask = sof_hda->link_dma_out_hda_used_mask; 91 92 list_for_each_entry(hstream, &bus->stream_list, list) { 93 struct hdac_ext_stream *hext_stream = 94 stream_to_hdac_ext_stream(hstream); 95 if (hstream->direction != substream->stream) 96 continue; 97 98 hda_stream = hstream_to_sof_hda_stream(hext_stream); 99 sdev = hda_stream->sdev; 100 chip = get_chip_info(sdev->pdata); 101 102 stream_idx = hstream->stream_tag - 1; 103 104 /* skip streams blocked by the ACE2+ allocator constraints */ 105 if ((concur_block_mask | seq_block_mask) & BIT(stream_idx)) 106 continue; 107 108 /* check if link is available */ 109 if (!hext_stream->link_locked) { 110 /* 111 * choose the first available link for platforms that do not have the 112 * PROCEN_FMT_QUIRK set. 113 */ 114 if (!(chip->quirks & SOF_INTEL_PROCEN_FMT_QUIRK)) { 115 res = hext_stream; 116 break; 117 } 118 119 if (hstream->opened) { 120 /* 121 * check if the stream tag matches the stream 122 * tag of one of the connected FEs 123 */ 124 if (hda_check_fes(rtd, stream_dir, 125 hstream->stream_tag)) { 126 res = hext_stream; 127 break; 128 } 129 } else { 130 res = hext_stream; 131 132 /* 133 * This must be a hostless stream. 134 * So reserve the host DMA stream. 135 */ 136 hda_stream->host_reserved = 1; 137 break; 138 } 139 } 140 } 141 142 if (res) { 143 /* Make sure that host and link DMA is decoupled. */ 144 snd_hdac_ext_stream_decouple_locked(bus, res, true); 145 146 res->link_locked = 1; 147 res->link_substream = substream; 148 149 stream_idx = res->hstream.stream_tag - 1; 150 if (is_sdw) 151 sof_hda->link_dma_active_sdw_mask[stream_dir] |= BIT(stream_idx); 152 else if (is_multi) 153 sof_hda->link_dma_active_multi_mask[stream_dir] |= BIT(stream_idx); 154 155 /* persistent OUT HDA/iDisp shadow, cleared only on CRST# */ 156 if (is_hda && is_play) 157 sof_hda->link_dma_out_hda_used_mask |= BIT(stream_idx); 158 } 159 160 return res; 161 } 162 163 static struct hdac_ext_stream *hda_get_hext_stream(struct snd_sof_dev *sdev, 164 struct snd_soc_dai *cpu_dai, 165 struct snd_pcm_substream *substream) 166 { 167 return snd_soc_dai_get_dma_data(cpu_dai, substream); 168 } 169 170 static struct hdac_ext_stream *hda_ipc4_get_hext_stream(struct snd_sof_dev *sdev, 171 struct snd_soc_dai *cpu_dai, 172 struct snd_pcm_substream *substream) 173 { 174 struct snd_sof_widget *pipe_widget; 175 struct sof_ipc4_pipeline *pipeline; 176 struct snd_sof_widget *swidget; 177 struct snd_soc_dapm_widget *w; 178 179 w = snd_soc_dai_get_widget(cpu_dai, substream->stream); 180 swidget = w->dobj.private; 181 pipe_widget = swidget->spipe->pipe_widget; 182 pipeline = pipe_widget->private; 183 184 /* mark pipeline so that it can be skipped during FE trigger */ 185 pipeline->skip_during_fe_trigger = true; 186 187 return snd_soc_dai_get_dma_data(cpu_dai, substream); 188 } 189 190 static struct hdac_ext_stream *hda_assign_hext_stream(struct snd_sof_dev *sdev, 191 struct snd_soc_dai *cpu_dai, 192 struct snd_pcm_substream *substream, 193 struct hdac_ext_link *hlink) 194 { 195 struct hdac_ext_stream *hext_stream; 196 enum hda_bus_ml_link_type link_type = hda_bus_ml_link_get_type(hlink); 197 198 hext_stream = hda_link_stream_assign(sof_to_bus(sdev), substream, link_type); 199 if (!hext_stream) 200 return NULL; 201 202 snd_soc_dai_set_dma_data(cpu_dai, substream, (void *)hext_stream); 203 204 return hext_stream; 205 } 206 207 static void hda_release_hext_stream(struct snd_sof_dev *sdev, struct snd_soc_dai *cpu_dai, 208 struct snd_pcm_substream *substream) 209 { 210 struct hdac_ext_stream *hext_stream = hda_get_hext_stream(sdev, cpu_dai, substream); 211 struct sof_intel_hda_dev *sof_hda = sdev->pdata->hw_pdata; 212 struct hdac_bus *bus = sof_to_bus(sdev); 213 int dir = substream->stream; 214 unsigned int stream_idx = hext_stream->hstream.stream_tag - 1; 215 216 /* 217 * Drop the stream index from the per-direction active concurrency masks. 218 * The two masks are mutually exclusive for a given stream/direction 219 * (and a stream of the SSP/DMIC kind appears in neither), so a blind 220 * clear of both is safe and lets us avoid having to remember the 221 * link type at allocation time. 222 */ 223 scoped_guard(spinlock_irq, &bus->reg_lock) { 224 sof_hda->link_dma_active_sdw_mask[dir] &= ~BIT(stream_idx); 225 sof_hda->link_dma_active_multi_mask[dir] &= ~BIT(stream_idx); 226 } 227 228 snd_soc_dai_set_dma_data(cpu_dai, substream, NULL); 229 snd_hdac_ext_stream_release(hext_stream, HDAC_EXT_STREAM_TYPE_LINK); 230 } 231 232 static void hda_setup_hext_stream(struct snd_sof_dev *sdev, struct hdac_ext_stream *hext_stream, 233 unsigned int format_val) 234 { 235 snd_hdac_ext_stream_setup(hext_stream, format_val); 236 } 237 238 static void hda_reset_hext_stream(struct snd_sof_dev *sdev, struct hdac_ext_stream *hext_stream) 239 { 240 snd_hdac_ext_stream_reset(hext_stream); 241 } 242 243 static void hda_codec_dai_set_stream(struct snd_sof_dev *sdev, 244 struct snd_pcm_substream *substream, 245 struct hdac_stream *hstream) 246 { 247 struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); 248 struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0); 249 250 /* set the hdac_stream in the codec dai */ 251 snd_soc_dai_set_stream(codec_dai, hstream, substream->stream); 252 } 253 254 static unsigned int hda_calc_stream_format(struct snd_sof_dev *sdev, 255 struct snd_pcm_substream *substream, 256 struct snd_pcm_hw_params *params) 257 { 258 struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); 259 struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0); 260 unsigned int link_bps; 261 unsigned int format_val; 262 unsigned int bits; 263 264 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 265 link_bps = codec_dai->driver->playback.sig_bits; 266 else 267 link_bps = codec_dai->driver->capture.sig_bits; 268 269 bits = snd_hdac_stream_format_bits(params_format(params), SNDRV_PCM_SUBFORMAT_STD, 270 link_bps); 271 format_val = snd_hdac_stream_format(params_channels(params), bits, params_rate(params)); 272 273 dev_dbg(sdev->dev, "format_val=%#x, rate=%d, ch=%d, format=%d\n", format_val, 274 params_rate(params), params_channels(params), params_format(params)); 275 276 return format_val; 277 } 278 279 static struct hdac_ext_link *hda_get_hlink(struct snd_sof_dev *sdev, 280 struct snd_pcm_substream *substream) 281 { 282 struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); 283 struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0); 284 struct hdac_bus *bus = sof_to_bus(sdev); 285 286 return snd_hdac_ext_bus_get_hlink_by_name(bus, codec_dai->component->name); 287 } 288 289 static unsigned int generic_calc_stream_format(struct snd_sof_dev *sdev, 290 struct snd_pcm_substream *substream, 291 struct snd_pcm_hw_params *params) 292 { 293 unsigned int format_val; 294 unsigned int bits; 295 296 bits = snd_hdac_stream_format_bits(params_format(params), SNDRV_PCM_SUBFORMAT_STD, 297 params_physical_width(params)); 298 format_val = snd_hdac_stream_format(params_channels(params), bits, params_rate(params)); 299 300 dev_dbg(sdev->dev, "format_val=%#x, rate=%d, ch=%d, format=%d\n", format_val, 301 params_rate(params), params_channels(params), params_format(params)); 302 303 return format_val; 304 } 305 306 static unsigned int dmic_calc_stream_format(struct snd_sof_dev *sdev, 307 struct snd_pcm_substream *substream, 308 struct snd_pcm_hw_params *params) 309 { 310 unsigned int format_val; 311 snd_pcm_format_t format; 312 unsigned int channels; 313 unsigned int width; 314 unsigned int bits; 315 316 channels = params_channels(params); 317 format = params_format(params); 318 width = params_physical_width(params); 319 320 if (format == SNDRV_PCM_FORMAT_S16_LE) { 321 format = SNDRV_PCM_FORMAT_S32_LE; 322 channels /= 2; 323 width = 32; 324 } 325 326 bits = snd_hdac_stream_format_bits(format, SNDRV_PCM_SUBFORMAT_STD, width); 327 format_val = snd_hdac_stream_format(channels, bits, params_rate(params)); 328 329 dev_dbg(sdev->dev, "format_val=%#x, rate=%d, ch=%d, format=%d\n", format_val, 330 params_rate(params), channels, format); 331 332 return format_val; 333 } 334 335 static struct hdac_ext_link *ssp_get_hlink(struct snd_sof_dev *sdev, 336 struct snd_pcm_substream *substream) 337 { 338 struct hdac_bus *bus = sof_to_bus(sdev); 339 340 return hdac_bus_eml_ssp_get_hlink(bus); 341 } 342 343 static struct hdac_ext_link *dmic_get_hlink(struct snd_sof_dev *sdev, 344 struct snd_pcm_substream *substream) 345 { 346 struct hdac_bus *bus = sof_to_bus(sdev); 347 348 return hdac_bus_eml_dmic_get_hlink(bus); 349 } 350 351 static struct hdac_ext_link *sdw_get_hlink(struct snd_sof_dev *sdev, 352 struct snd_pcm_substream *substream) 353 { 354 struct hdac_bus *bus = sof_to_bus(sdev); 355 356 return hdac_bus_eml_sdw_get_hlink(bus); 357 } 358 359 static int hda_ipc4_pre_trigger(struct snd_sof_dev *sdev, struct snd_soc_dai *cpu_dai, 360 struct snd_pcm_substream *substream, int cmd) 361 { 362 struct sof_ipc4_fw_data *ipc4_data = sdev->private; 363 struct snd_sof_widget *pipe_widget; 364 struct sof_ipc4_pipeline *pipeline; 365 struct snd_sof_widget *swidget; 366 struct snd_soc_dapm_widget *w; 367 int ret = 0; 368 369 w = snd_soc_dai_get_widget(cpu_dai, substream->stream); 370 swidget = w->dobj.private; 371 pipe_widget = swidget->spipe->pipe_widget; 372 pipeline = pipe_widget->private; 373 374 if (pipe_widget->instance_id < 0) 375 return 0; 376 377 guard(mutex)(&ipc4_data->pipeline_state_mutex); 378 379 switch (cmd) { 380 case SNDRV_PCM_TRIGGER_START: 381 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: 382 break; 383 case SNDRV_PCM_TRIGGER_PAUSE_PUSH: 384 case SNDRV_PCM_TRIGGER_SUSPEND: 385 case SNDRV_PCM_TRIGGER_STOP: 386 ret = sof_ipc4_set_pipeline_state(sdev, pipe_widget->instance_id, 387 SOF_IPC4_PIPE_PAUSED); 388 if (ret < 0) 389 return ret; 390 391 pipeline->state = SOF_IPC4_PIPE_PAUSED; 392 393 break; 394 default: 395 dev_err(sdev->dev, "unknown trigger command %d\n", cmd); 396 ret = -EINVAL; 397 } 398 399 return ret; 400 } 401 402 static int hda_trigger(struct snd_sof_dev *sdev, struct snd_soc_dai *cpu_dai, 403 struct snd_pcm_substream *substream, int cmd) 404 { 405 struct hdac_ext_stream *hext_stream = snd_soc_dai_get_dma_data(cpu_dai, substream); 406 407 switch (cmd) { 408 case SNDRV_PCM_TRIGGER_START: 409 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: 410 snd_hdac_ext_stream_start(hext_stream); 411 break; 412 case SNDRV_PCM_TRIGGER_PAUSE_PUSH: 413 /* 414 * Save the LLP registers since in case of PAUSE the LLP 415 * register are not reset to 0, the delay calculation will use 416 * the saved offsets for compensating the delay calculation. 417 */ 418 hext_stream->pplcllpl = readl(hext_stream->pplc_addr + AZX_REG_PPLCLLPL); 419 hext_stream->pplcllpu = readl(hext_stream->pplc_addr + AZX_REG_PPLCLLPU); 420 snd_hdac_ext_stream_clear(hext_stream); 421 break; 422 case SNDRV_PCM_TRIGGER_SUSPEND: 423 case SNDRV_PCM_TRIGGER_STOP: 424 hext_stream->pplcllpl = 0; 425 hext_stream->pplcllpu = 0; 426 snd_hdac_ext_stream_clear(hext_stream); 427 break; 428 default: 429 dev_err(sdev->dev, "unknown trigger command %d\n", cmd); 430 return -EINVAL; 431 } 432 433 return 0; 434 } 435 436 static int hda_ipc4_post_trigger(struct snd_sof_dev *sdev, struct snd_soc_dai *cpu_dai, 437 struct snd_pcm_substream *substream, int cmd) 438 { 439 struct sof_ipc4_fw_data *ipc4_data = sdev->private; 440 struct snd_sof_widget *pipe_widget; 441 struct sof_ipc4_pipeline *pipeline; 442 struct snd_sof_widget *swidget; 443 struct snd_soc_dapm_widget *w; 444 int ret = 0; 445 446 w = snd_soc_dai_get_widget(cpu_dai, substream->stream); 447 swidget = w->dobj.private; 448 pipe_widget = swidget->spipe->pipe_widget; 449 pipeline = pipe_widget->private; 450 451 if (pipe_widget->instance_id < 0) 452 return 0; 453 454 guard(mutex)(&ipc4_data->pipeline_state_mutex); 455 456 switch (cmd) { 457 case SNDRV_PCM_TRIGGER_START: 458 if (pipeline->state != SOF_IPC4_PIPE_PAUSED) { 459 ret = sof_ipc4_set_pipeline_state(sdev, pipe_widget->instance_id, 460 SOF_IPC4_PIPE_PAUSED); 461 if (ret < 0) 462 return ret; 463 464 pipeline->state = SOF_IPC4_PIPE_PAUSED; 465 } 466 467 ret = sof_ipc4_set_pipeline_state(sdev, pipe_widget->instance_id, 468 SOF_IPC4_PIPE_RUNNING); 469 if (ret < 0) 470 return ret; 471 472 pipeline->state = SOF_IPC4_PIPE_RUNNING; 473 swidget->spipe->started_count++; 474 break; 475 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: 476 ret = sof_ipc4_set_pipeline_state(sdev, pipe_widget->instance_id, 477 SOF_IPC4_PIPE_RUNNING); 478 if (ret < 0) 479 return ret; 480 481 pipeline->state = SOF_IPC4_PIPE_RUNNING; 482 break; 483 case SNDRV_PCM_TRIGGER_SUSPEND: 484 case SNDRV_PCM_TRIGGER_STOP: 485 /* 486 * STOP/SUSPEND trigger is invoked only once when all users of this pipeline have 487 * been stopped. So, clear the started_count so that the pipeline can be reset 488 */ 489 swidget->spipe->started_count = 0; 490 break; 491 case SNDRV_PCM_TRIGGER_PAUSE_PUSH: 492 break; 493 default: 494 dev_err(sdev->dev, "unknown trigger command %d\n", cmd); 495 ret = -EINVAL; 496 break; 497 } 498 499 return ret; 500 } 501 502 static const struct hda_dai_widget_dma_ops hda_ipc4_dma_ops = { 503 .get_hext_stream = hda_ipc4_get_hext_stream, 504 .assign_hext_stream = hda_assign_hext_stream, 505 .release_hext_stream = hda_release_hext_stream, 506 .setup_hext_stream = hda_setup_hext_stream, 507 .reset_hext_stream = hda_reset_hext_stream, 508 .pre_trigger = hda_ipc4_pre_trigger, 509 .trigger = hda_trigger, 510 .post_trigger = hda_ipc4_post_trigger, 511 .codec_dai_set_stream = hda_codec_dai_set_stream, 512 .calc_stream_format = hda_calc_stream_format, 513 .get_hlink = hda_get_hlink, 514 }; 515 516 static const struct hda_dai_widget_dma_ops ssp_ipc4_dma_ops = { 517 .get_hext_stream = hda_ipc4_get_hext_stream, 518 .assign_hext_stream = hda_assign_hext_stream, 519 .release_hext_stream = hda_release_hext_stream, 520 .setup_hext_stream = hda_setup_hext_stream, 521 .reset_hext_stream = hda_reset_hext_stream, 522 .pre_trigger = hda_ipc4_pre_trigger, 523 .trigger = hda_trigger, 524 .post_trigger = hda_ipc4_post_trigger, 525 .calc_stream_format = generic_calc_stream_format, 526 .get_hlink = ssp_get_hlink, 527 }; 528 529 static const struct hda_dai_widget_dma_ops dmic_ipc4_dma_ops = { 530 .get_hext_stream = hda_ipc4_get_hext_stream, 531 .assign_hext_stream = hda_assign_hext_stream, 532 .release_hext_stream = hda_release_hext_stream, 533 .setup_hext_stream = hda_setup_hext_stream, 534 .reset_hext_stream = hda_reset_hext_stream, 535 .pre_trigger = hda_ipc4_pre_trigger, 536 .trigger = hda_trigger, 537 .post_trigger = hda_ipc4_post_trigger, 538 .calc_stream_format = dmic_calc_stream_format, 539 .get_hlink = dmic_get_hlink, 540 }; 541 542 static const struct hda_dai_widget_dma_ops sdw_ipc4_dma_ops = { 543 .get_hext_stream = hda_ipc4_get_hext_stream, 544 .assign_hext_stream = hda_assign_hext_stream, 545 .release_hext_stream = hda_release_hext_stream, 546 .setup_hext_stream = hda_setup_hext_stream, 547 .reset_hext_stream = hda_reset_hext_stream, 548 .pre_trigger = hda_ipc4_pre_trigger, 549 .trigger = hda_trigger, 550 .post_trigger = hda_ipc4_post_trigger, 551 .calc_stream_format = generic_calc_stream_format, 552 .get_hlink = sdw_get_hlink, 553 }; 554 555 static const struct hda_dai_widget_dma_ops hda_ipc4_chain_dma_ops = { 556 .get_hext_stream = hda_get_hext_stream, 557 .assign_hext_stream = hda_assign_hext_stream, 558 .release_hext_stream = hda_release_hext_stream, 559 .setup_hext_stream = hda_setup_hext_stream, 560 .reset_hext_stream = hda_reset_hext_stream, 561 .trigger = hda_trigger, 562 .codec_dai_set_stream = hda_codec_dai_set_stream, 563 .calc_stream_format = hda_calc_stream_format, 564 .get_hlink = hda_get_hlink, 565 }; 566 567 static const struct hda_dai_widget_dma_ops sdw_ipc4_chain_dma_ops = { 568 .get_hext_stream = hda_get_hext_stream, 569 .assign_hext_stream = hda_assign_hext_stream, 570 .release_hext_stream = hda_release_hext_stream, 571 .setup_hext_stream = hda_setup_hext_stream, 572 .reset_hext_stream = hda_reset_hext_stream, 573 .trigger = hda_trigger, 574 .calc_stream_format = generic_calc_stream_format, 575 .get_hlink = sdw_get_hlink, 576 }; 577 578 static int hda_ipc3_post_trigger(struct snd_sof_dev *sdev, struct snd_soc_dai *cpu_dai, 579 struct snd_pcm_substream *substream, int cmd) 580 { 581 struct snd_soc_dapm_widget *w = snd_soc_dai_get_widget(cpu_dai, substream->stream); 582 583 switch (cmd) { 584 case SNDRV_PCM_TRIGGER_SUSPEND: 585 case SNDRV_PCM_TRIGGER_STOP: 586 { 587 struct snd_sof_dai_config_data data = { 0 }; 588 int ret; 589 590 data.dai_data = DMA_CHAN_INVALID; 591 ret = hda_dai_config(w, SOF_DAI_CONFIG_FLAGS_HW_FREE, &data); 592 if (ret < 0) 593 return ret; 594 595 break; 596 } 597 case SNDRV_PCM_TRIGGER_PAUSE_PUSH: 598 return hda_dai_config(w, SOF_DAI_CONFIG_FLAGS_PAUSE, NULL); 599 default: 600 break; 601 } 602 603 return 0; 604 } 605 606 static const struct hda_dai_widget_dma_ops hda_ipc3_dma_ops = { 607 .get_hext_stream = hda_get_hext_stream, 608 .assign_hext_stream = hda_assign_hext_stream, 609 .release_hext_stream = hda_release_hext_stream, 610 .setup_hext_stream = hda_setup_hext_stream, 611 .reset_hext_stream = hda_reset_hext_stream, 612 .trigger = hda_trigger, 613 .post_trigger = hda_ipc3_post_trigger, 614 .codec_dai_set_stream = hda_codec_dai_set_stream, 615 .calc_stream_format = hda_calc_stream_format, 616 .get_hlink = hda_get_hlink, 617 }; 618 619 static struct hdac_ext_stream * 620 hda_dspless_get_hext_stream(struct snd_sof_dev *sdev, struct snd_soc_dai *cpu_dai, 621 struct snd_pcm_substream *substream) 622 { 623 struct hdac_stream *hstream = substream->runtime->private_data; 624 625 return stream_to_hdac_ext_stream(hstream); 626 } 627 628 static void hda_dspless_setup_hext_stream(struct snd_sof_dev *sdev, 629 struct hdac_ext_stream *hext_stream, 630 unsigned int format_val) 631 { 632 /* 633 * Save the format_val which was adjusted by the maxbps of the codec. 634 * This information is not available on the FE side since there we are 635 * using dummy_codec. 636 */ 637 hext_stream->hstream.format_val = format_val; 638 } 639 640 static const struct hda_dai_widget_dma_ops hda_dspless_dma_ops = { 641 .get_hext_stream = hda_dspless_get_hext_stream, 642 .setup_hext_stream = hda_dspless_setup_hext_stream, 643 .codec_dai_set_stream = hda_codec_dai_set_stream, 644 .calc_stream_format = hda_calc_stream_format, 645 .get_hlink = hda_get_hlink, 646 }; 647 648 static const struct hda_dai_widget_dma_ops sdw_dspless_dma_ops = { 649 .get_hext_stream = hda_dspless_get_hext_stream, 650 .setup_hext_stream = hda_dspless_setup_hext_stream, 651 .calc_stream_format = generic_calc_stream_format, 652 .get_hlink = sdw_get_hlink, 653 }; 654 655 #endif 656 657 const struct hda_dai_widget_dma_ops * 658 hda_select_dai_widget_ops(struct snd_sof_dev *sdev, struct snd_sof_widget *swidget) 659 { 660 #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_LINK) 661 struct snd_sof_dai *sdai; 662 const struct sof_intel_dsp_desc *chip; 663 664 chip = get_chip_info(sdev->pdata); 665 sdai = swidget->private; 666 667 if (sdev->dspless_mode_selected) { 668 switch (sdai->type) { 669 case SOF_DAI_INTEL_HDA: 670 return &hda_dspless_dma_ops; 671 case SOF_DAI_INTEL_ALH: 672 if (chip->hw_ip_version < SOF_INTEL_ACE_2_0) 673 return NULL; 674 return &sdw_dspless_dma_ops; 675 default: 676 return NULL; 677 } 678 } 679 680 switch (sdev->pdata->ipc_type) { 681 case SOF_IPC_TYPE_3: 682 { 683 struct sof_dai_private_data *private = sdai->private; 684 685 if (private->dai_config->type == SOF_DAI_INTEL_HDA) 686 return &hda_ipc3_dma_ops; 687 break; 688 } 689 case SOF_IPC_TYPE_4: 690 { 691 struct snd_sof_widget *pipe_widget = swidget->spipe->pipe_widget; 692 struct sof_ipc4_pipeline *pipeline = pipe_widget->private; 693 694 switch (sdai->type) { 695 case SOF_DAI_INTEL_HDA: 696 if (pipeline->use_chain_dma) 697 return &hda_ipc4_chain_dma_ops; 698 699 return &hda_ipc4_dma_ops; 700 case SOF_DAI_INTEL_SSP: 701 if (chip->hw_ip_version < SOF_INTEL_ACE_2_0) 702 return NULL; 703 return &ssp_ipc4_dma_ops; 704 case SOF_DAI_INTEL_DMIC: 705 if (chip->hw_ip_version < SOF_INTEL_ACE_2_0) 706 return NULL; 707 return &dmic_ipc4_dma_ops; 708 case SOF_DAI_INTEL_ALH: 709 if (chip->hw_ip_version < SOF_INTEL_ACE_2_0) 710 return NULL; 711 if (pipeline->use_chain_dma) 712 return &sdw_ipc4_chain_dma_ops; 713 return &sdw_ipc4_dma_ops; 714 715 default: 716 break; 717 } 718 break; 719 } 720 default: 721 break; 722 } 723 #endif 724 return NULL; 725 } 726