at master 870 lines 25 kB view raw
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 7// 8// Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> 9// 10// PCM Layer, interface between ALSA and IPC. 11// 12 13#include <linux/pm_runtime.h> 14#include <sound/pcm_params.h> 15#include <sound/sof.h> 16#include <trace/events/sof.h> 17#include "sof-of-dev.h" 18#include "sof-priv.h" 19#include "sof-audio.h" 20#include "sof-utils.h" 21#include "ops.h" 22 23/* 24 * sof pcm period elapse work 25 */ 26static void snd_sof_pcm_period_elapsed_work(struct work_struct *work) 27{ 28 struct snd_sof_pcm_stream *sps = 29 container_of(work, struct snd_sof_pcm_stream, 30 period_elapsed_work); 31 32 snd_pcm_period_elapsed(sps->substream); 33} 34 35void snd_sof_pcm_init_elapsed_work(struct work_struct *work) 36{ 37 INIT_WORK(work, snd_sof_pcm_period_elapsed_work); 38} 39 40/* 41 * sof pcm period elapse, this could be called at irq thread context. 42 */ 43void snd_sof_pcm_period_elapsed(struct snd_pcm_substream *substream) 44{ 45 struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); 46 struct snd_soc_component *component = 47 snd_soc_rtdcom_lookup(rtd, SOF_AUDIO_PCM_DRV_NAME); 48 struct snd_sof_pcm *spcm; 49 50 spcm = snd_sof_find_spcm_dai(component, rtd); 51 if (!spcm) { 52 dev_err(component->dev, 53 "error: period elapsed for unknown stream!\n"); 54 return; 55 } 56 57 /* 58 * snd_pcm_period_elapsed() can be called in interrupt context 59 * before IRQ_HANDLED is returned. Inside snd_pcm_period_elapsed(), 60 * when the PCM is done draining or xrun happened, a STOP IPC will 61 * then be sent and this IPC will hit IPC timeout. 62 * To avoid sending IPC before the previous IPC is handled, we 63 * schedule delayed work here to call the snd_pcm_period_elapsed(). 64 */ 65 schedule_work(&spcm->stream[substream->stream].period_elapsed_work); 66} 67EXPORT_SYMBOL(snd_sof_pcm_period_elapsed); 68 69static int 70sof_pcm_setup_connected_widgets(struct snd_sof_dev *sdev, struct snd_soc_pcm_runtime *rtd, 71 struct snd_sof_pcm *spcm, struct snd_pcm_hw_params *params, 72 struct snd_sof_platform_stream_params *platform_params, int dir) 73{ 74 struct snd_soc_dai *dai; 75 int ret, j; 76 77 /* query DAPM for list of connected widgets and set them up */ 78 for_each_rtd_cpu_dais(rtd, j, dai) { 79 struct snd_soc_dapm_widget_list *list; 80 81 ret = snd_soc_dapm_dai_get_connected_widgets(dai, dir, &list, 82 dpcm_end_walk_at_be); 83 if (ret < 0) { 84 spcm_err(spcm, dir, "dai %s has no valid %s path\n", 85 dai->name, snd_pcm_direction_name(dir)); 86 return ret; 87 } 88 89 spcm->stream[dir].list = list; 90 91 ret = sof_widget_list_prepare(sdev, spcm, params, platform_params, dir); 92 if (ret < 0) { 93 spcm_err(spcm, dir, "widget list prepare failed\n"); 94 spcm->stream[dir].list = NULL; 95 snd_soc_dapm_dai_free_widgets(&list); 96 return ret; 97 } 98 } 99 100 return 0; 101} 102 103static struct snd_sof_widget *snd_sof_find_swidget_by_comp_id(struct snd_sof_dev *sdev, 104 int comp_id) 105{ 106 struct snd_sof_widget *swidget; 107 108 list_for_each_entry(swidget, &sdev->widget_list, list) { 109 if (comp_id == swidget->comp_id) 110 return swidget; 111 } 112 113 return NULL; 114} 115 116static int sof_pcm_hw_params(struct snd_soc_component *component, 117 struct snd_pcm_substream *substream, 118 struct snd_pcm_hw_params *params) 119{ 120 struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component); 121 struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); 122 const struct sof_ipc_tplg_ops *tplg_ops = sof_ipc_get_ops(sdev, tplg); 123 const struct sof_ipc_pcm_ops *pcm_ops = sof_ipc_get_ops(sdev, pcm); 124 struct snd_sof_platform_stream_params *platform_params; 125 struct snd_pcm_runtime *runtime = substream->runtime; 126 struct snd_sof_widget *host_widget; 127 struct snd_sof_pcm *spcm; 128 int ret; 129 130 /* nothing to do for BE */ 131 if (rtd->dai_link->no_pcm) 132 return 0; 133 134 spcm = snd_sof_find_spcm_dai(component, rtd); 135 if (!spcm) 136 return -EINVAL; 137 138 spcm_dbg(spcm, substream->stream, "Entry: hw_params\n"); 139 140 if (!sdev->dspless_mode_selected) { 141 /* 142 * Make sure that the DSP is booted up, which might not be the 143 * case if the on-demand DSP boot is used 144 */ 145 ret = snd_sof_boot_dsp_firmware(sdev); 146 if (ret) 147 return ret; 148 } 149 150 /* 151 * Handle repeated calls to hw_params() without free_pcm() in 152 * between. At least ALSA OSS emulation depends on this. 153 */ 154 if (spcm->prepared[substream->stream] && pcm_ops && pcm_ops->hw_free) { 155 ret = pcm_ops->hw_free(component, substream); 156 if (ret < 0) 157 return ret; 158 159 spcm->prepared[substream->stream] = false; 160 } 161 162 platform_params = &spcm->platform_params[substream->stream]; 163 ret = snd_sof_pcm_platform_hw_params(sdev, substream, params, platform_params); 164 if (ret < 0) { 165 spcm_err(spcm, substream->stream, "platform hw params failed\n"); 166 return ret; 167 } 168 169 /* if this is a repeated hw_params without hw_free, skip setting up widgets */ 170 if (!spcm->stream[substream->stream].list) { 171 ret = sof_pcm_setup_connected_widgets(sdev, rtd, spcm, params, platform_params, 172 substream->stream); 173 if (ret < 0) 174 return ret; 175 } 176 177 if (!sdev->dspless_mode_selected) { 178 int host_comp_id = spcm->stream[substream->stream].comp_id; 179 180 host_widget = snd_sof_find_swidget_by_comp_id(sdev, host_comp_id); 181 if (!host_widget) { 182 spcm_err(spcm, substream->stream, 183 "failed to find host widget with comp_id %d\n", host_comp_id); 184 return -EINVAL; 185 } 186 187 /* set the host DMA ID */ 188 if (tplg_ops && tplg_ops->host_config) 189 tplg_ops->host_config(sdev, host_widget, platform_params); 190 } 191 192 /* create compressed page table for audio firmware */ 193 if (runtime->buffer_changed) { 194 struct snd_dma_buffer *dmab = snd_pcm_get_dma_buf(substream); 195 196 ret = snd_sof_create_page_table(component->dev, dmab, 197 spcm->stream[substream->stream].page_table.area, 198 runtime->dma_bytes); 199 if (ret < 0) 200 return ret; 201 } 202 203 /* save pcm hw_params */ 204 memcpy(&spcm->params[substream->stream], params, sizeof(*params)); 205 206 return 0; 207} 208 209static int sof_pcm_stream_free(struct snd_sof_dev *sdev, 210 struct snd_pcm_substream *substream, 211 struct snd_sof_pcm *spcm, int dir, 212 bool free_widget_list) 213{ 214 const struct sof_ipc_pcm_ops *pcm_ops = sof_ipc_get_ops(sdev, pcm); 215 int ret; 216 int err = 0; 217 218 if (spcm->prepared[substream->stream]) { 219 /* stop DMA first if needed */ 220 if (pcm_ops && pcm_ops->platform_stop_during_hw_free) 221 snd_sof_pcm_platform_trigger(sdev, substream, 222 SNDRV_PCM_TRIGGER_STOP); 223 224 /* free PCM in the DSP */ 225 if (pcm_ops && pcm_ops->hw_free) { 226 ret = pcm_ops->hw_free(sdev->component, substream); 227 if (ret < 0) { 228 spcm_err(spcm, substream->stream, 229 "pcm_ops->hw_free failed %d\n", ret); 230 err = ret; 231 } 232 } 233 234 spcm->prepared[substream->stream] = false; 235 spcm->pending_stop[substream->stream] = false; 236 } 237 238 /* reset the DMA */ 239 ret = snd_sof_pcm_platform_hw_free(sdev, substream); 240 if (ret < 0) { 241 spcm_err(spcm, substream->stream, 242 "platform hw free failed %d\n", ret); 243 if (!err) 244 err = ret; 245 } 246 247 /* free widget list */ 248 if (free_widget_list) { 249 ret = sof_widget_list_free(sdev, spcm, dir); 250 if (ret < 0) { 251 spcm_err(spcm, substream->stream, 252 "sof_widget_list_free failed %d\n", ret); 253 if (!err) 254 err = ret; 255 } 256 } 257 258 return err; 259} 260 261int sof_pcm_free_all_streams(struct snd_sof_dev *sdev) 262{ 263 struct snd_pcm_substream *substream; 264 struct snd_sof_pcm *spcm; 265 int dir, ret; 266 267 list_for_each_entry(spcm, &sdev->pcm_list, list) { 268 for_each_pcm_streams(dir) { 269 substream = spcm->stream[dir].substream; 270 271 if (!substream || !substream->runtime || 272 spcm->stream[dir].suspend_ignored) 273 continue; 274 275 if (spcm->stream[dir].list) { 276 ret = sof_pcm_stream_free(sdev, substream, spcm, 277 dir, true); 278 if (ret < 0) 279 return ret; 280 } 281 } 282 } 283 284 return 0; 285} 286 287static int sof_pcm_hw_free(struct snd_soc_component *component, 288 struct snd_pcm_substream *substream) 289{ 290 struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); 291 struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component); 292 struct snd_sof_pcm *spcm; 293 int ret; 294 295 /* nothing to do for BE */ 296 if (rtd->dai_link->no_pcm) 297 return 0; 298 299 spcm = snd_sof_find_spcm_dai(component, rtd); 300 if (!spcm) 301 return -EINVAL; 302 303 spcm_dbg(spcm, substream->stream, "Entry: hw_free\n"); 304 305 ret = sof_pcm_stream_free(sdev, substream, spcm, substream->stream, true); 306 307 /* unprepare and free the list of DAPM widgets */ 308 sof_widget_list_unprepare(sdev, spcm, substream->stream); 309 310 cancel_work_sync(&spcm->stream[substream->stream].period_elapsed_work); 311 312 return ret; 313} 314 315static int sof_pcm_prepare(struct snd_soc_component *component, 316 struct snd_pcm_substream *substream) 317{ 318 struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); 319 struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component); 320 const struct sof_ipc_pcm_ops *pcm_ops = sof_ipc_get_ops(sdev, pcm); 321 struct snd_sof_platform_stream_params *platform_params; 322 struct snd_soc_dapm_widget_list *list; 323 struct snd_pcm_hw_params *params; 324 struct snd_sof_pcm *spcm; 325 int dir = substream->stream; 326 int ret; 327 328 /* nothing to do for BE */ 329 if (rtd->dai_link->no_pcm) 330 return 0; 331 332 spcm = snd_sof_find_spcm_dai(component, rtd); 333 if (!spcm) 334 return -EINVAL; 335 336 spcm_dbg(spcm, substream->stream, "Entry: prepare\n"); 337 338 if (spcm->prepared[substream->stream]) { 339 if (!spcm->pending_stop[substream->stream]) 340 return 0; 341 342 /* 343 * this case should be reached in case of xruns where we absolutely 344 * want to free-up and reset all PCM/DMA resources 345 */ 346 ret = sof_pcm_stream_free(sdev, substream, spcm, substream->stream, true); 347 if (ret < 0) 348 return ret; 349 } 350 351 ret = sof_pcm_hw_params(component, substream, &spcm->params[substream->stream]); 352 if (ret < 0) { 353 spcm_err(spcm, substream->stream, 354 "failed to set hw_params after resume\n"); 355 return ret; 356 } 357 358 list = spcm->stream[dir].list; 359 params = &spcm->params[substream->stream]; 360 platform_params = &spcm->platform_params[substream->stream]; 361 ret = sof_widget_list_setup(sdev, spcm, params, platform_params, dir); 362 if (ret < 0) { 363 dev_err(sdev->dev, "failed widget list set up for pcm %d dir %d\n", 364 spcm->pcm.pcm_id, dir); 365 spcm->stream[dir].list = NULL; 366 snd_soc_dapm_dai_free_widgets(&list); 367 return ret; 368 } 369 370 if (pcm_ops && pcm_ops->hw_params) { 371 ret = pcm_ops->hw_params(component, substream, params, platform_params); 372 if (ret < 0) 373 return ret; 374 } 375 376 spcm->prepared[substream->stream] = true; 377 378 return 0; 379} 380 381/* 382 * FE dai link trigger actions are always executed in non-atomic context because 383 * they involve IPC's. 384 */ 385static int sof_pcm_trigger(struct snd_soc_component *component, 386 struct snd_pcm_substream *substream, int cmd) 387{ 388 struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); 389 struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component); 390 const struct sof_ipc_pcm_ops *pcm_ops = sof_ipc_get_ops(sdev, pcm); 391 struct snd_sof_pcm *spcm; 392 bool reset_hw_params = false; 393 bool ipc_first = false; 394 int ret = 0; 395 396 /* nothing to do for BE */ 397 if (rtd->dai_link->no_pcm) 398 return 0; 399 400 spcm = snd_sof_find_spcm_dai(component, rtd); 401 if (!spcm) 402 return -EINVAL; 403 404 spcm_dbg(spcm, substream->stream, "Entry: trigger (cmd: %d)\n", cmd); 405 406 spcm->pending_stop[substream->stream] = false; 407 408 switch (cmd) { 409 case SNDRV_PCM_TRIGGER_PAUSE_PUSH: 410 ipc_first = true; 411 break; 412 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: 413 if (pcm_ops && pcm_ops->ipc_first_on_start) 414 ipc_first = true; 415 break; 416 case SNDRV_PCM_TRIGGER_START: 417 if (spcm->stream[substream->stream].suspend_ignored) { 418 /* 419 * This case will be triggered when INFO_RESUME is 420 * not supported, no need to re-start streams that 421 * remained enabled in D0ix. 422 */ 423 spcm->stream[substream->stream].suspend_ignored = false; 424 return 0; 425 } 426 427 if (pcm_ops && pcm_ops->ipc_first_on_start) 428 ipc_first = true; 429 break; 430 case SNDRV_PCM_TRIGGER_SUSPEND: 431 /* 432 * If DSP D0I3 is allowed during S0iX, set the suspend_ignored flag for 433 * D0I3-compatible streams to keep the firmware pipeline running 434 */ 435 if (pcm_ops && pcm_ops->d0i3_supported_in_s0ix && 436 sdev->system_suspend_target == SOF_SUSPEND_S0IX && 437 spcm->stream[substream->stream].d0i3_compatible) { 438 spcm->stream[substream->stream].suspend_ignored = true; 439 return 0; 440 } 441 442 /* On suspend the DMA must be stopped in DSPless mode */ 443 if (sdev->dspless_mode_selected) 444 reset_hw_params = true; 445 446 fallthrough; 447 case SNDRV_PCM_TRIGGER_STOP: 448 ipc_first = true; 449 if (pcm_ops && pcm_ops->reset_hw_params_during_stop) 450 reset_hw_params = true; 451 break; 452 default: 453 spcm_err(spcm, substream->stream, "Unhandled trigger cmd %d\n", cmd); 454 return -EINVAL; 455 } 456 457 if (!ipc_first) 458 snd_sof_pcm_platform_trigger(sdev, substream, cmd); 459 460 if (pcm_ops && pcm_ops->trigger) 461 ret = pcm_ops->trigger(component, substream, cmd); 462 463 switch (cmd) { 464 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: 465 case SNDRV_PCM_TRIGGER_START: 466 /* invoke platform trigger to start DMA only if pcm_ops is successful */ 467 if (ipc_first && !ret) 468 snd_sof_pcm_platform_trigger(sdev, substream, cmd); 469 break; 470 case SNDRV_PCM_TRIGGER_SUSPEND: 471 case SNDRV_PCM_TRIGGER_PAUSE_PUSH: 472 case SNDRV_PCM_TRIGGER_STOP: 473 /* invoke platform trigger to stop DMA even if pcm_ops isn't set or if it failed */ 474 if (!pcm_ops || !pcm_ops->platform_stop_during_hw_free) 475 snd_sof_pcm_platform_trigger(sdev, substream, cmd); 476 477 /* 478 * set the pending_stop flag to indicate that pipeline stop has been delayed. 479 * This will be used later to stop the pipelines during prepare when recovering 480 * from xruns. 481 */ 482 if (pcm_ops && pcm_ops->platform_stop_during_hw_free && 483 cmd == SNDRV_PCM_TRIGGER_STOP) 484 spcm->pending_stop[substream->stream] = true; 485 break; 486 default: 487 break; 488 } 489 490 /* free PCM if reset_hw_params is set and the STOP IPC is successful */ 491 if (!ret && reset_hw_params) 492 ret = sof_pcm_stream_free(sdev, substream, spcm, substream->stream, false); 493 494 return ret; 495} 496 497static snd_pcm_uframes_t sof_pcm_pointer(struct snd_soc_component *component, 498 struct snd_pcm_substream *substream) 499{ 500 struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); 501 struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component); 502 const struct sof_ipc_pcm_ops *pcm_ops = sof_ipc_get_ops(sdev, pcm); 503 struct snd_sof_pcm *spcm; 504 snd_pcm_uframes_t host, dai; 505 int ret = -EOPNOTSUPP; 506 507 /* nothing to do for BE */ 508 if (rtd->dai_link->no_pcm) 509 return 0; 510 511 if (pcm_ops && pcm_ops->pointer) 512 ret = pcm_ops->pointer(component, substream, &host); 513 514 if (ret != -EOPNOTSUPP) 515 return ret ? ret : host; 516 517 /* use dsp ops pointer callback directly if set */ 518 if (sof_ops(sdev)->pcm_pointer) 519 return sof_ops(sdev)->pcm_pointer(sdev, substream); 520 521 spcm = snd_sof_find_spcm_dai(component, rtd); 522 if (!spcm) 523 return -EINVAL; 524 525 /* read position from DSP */ 526 host = bytes_to_frames(substream->runtime, 527 spcm->stream[substream->stream].posn.host_posn); 528 dai = bytes_to_frames(substream->runtime, 529 spcm->stream[substream->stream].posn.dai_posn); 530 531 trace_sof_pcm_pointer_position(sdev, spcm, substream, host, dai); 532 533 return host; 534} 535 536static int sof_pcm_open(struct snd_soc_component *component, 537 struct snd_pcm_substream *substream) 538{ 539 struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); 540 struct snd_pcm_runtime *runtime = substream->runtime; 541 struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component); 542 const struct snd_sof_dsp_ops *ops = sof_ops(sdev); 543 struct snd_sof_pcm *spcm; 544 struct snd_soc_tplg_stream_caps *caps; 545 int ret; 546 547 /* nothing to do for BE */ 548 if (rtd->dai_link->no_pcm) 549 return 0; 550 551 spcm = snd_sof_find_spcm_dai(component, rtd); 552 if (!spcm) 553 return -EINVAL; 554 555 spcm_dbg(spcm, substream->stream, "Entry: open\n"); 556 557 caps = &spcm->pcm.caps[substream->stream]; 558 559 /* set runtime config */ 560 runtime->hw.info = ops->hw_info; /* platform-specific */ 561 562 /* set any runtime constraints based on topology */ 563 runtime->hw.formats = le64_to_cpu(caps->formats); 564 runtime->hw.period_bytes_min = le32_to_cpu(caps->period_size_min); 565 runtime->hw.period_bytes_max = le32_to_cpu(caps->period_size_max); 566 runtime->hw.periods_min = le32_to_cpu(caps->periods_min); 567 runtime->hw.periods_max = le32_to_cpu(caps->periods_max); 568 569 /* 570 * caps->buffer_size_min is not used since the 571 * snd_pcm_hardware structure only defines buffer_bytes_max 572 */ 573 runtime->hw.buffer_bytes_max = le32_to_cpu(caps->buffer_size_max); 574 575 /* set wait time - TODO: come from topology */ 576 substream->wait_time = 500; 577 578 spcm->stream[substream->stream].posn.host_posn = 0; 579 spcm->stream[substream->stream].posn.dai_posn = 0; 580 spcm->stream[substream->stream].substream = substream; 581 spcm->prepared[substream->stream] = false; 582 583 ret = snd_sof_pcm_platform_open(sdev, substream); 584 if (ret < 0) { 585 spcm_err(spcm, substream->stream, 586 "platform pcm open failed %d\n", ret); 587 return ret; 588 } 589 590 spcm_dbg(spcm, substream->stream, "period bytes min %zd, max %zd\n", 591 runtime->hw.period_bytes_min, runtime->hw.period_bytes_max); 592 spcm_dbg(spcm, substream->stream, "period count min %d, max %d\n", 593 runtime->hw.periods_min, runtime->hw.periods_max); 594 spcm_dbg(spcm, substream->stream, "buffer bytes max %zd\n", runtime->hw.buffer_bytes_max); 595 596 return 0; 597} 598 599static int sof_pcm_close(struct snd_soc_component *component, 600 struct snd_pcm_substream *substream) 601{ 602 struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); 603 struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component); 604 struct snd_sof_pcm *spcm; 605 int err; 606 607 /* nothing to do for BE */ 608 if (rtd->dai_link->no_pcm) 609 return 0; 610 611 spcm = snd_sof_find_spcm_dai(component, rtd); 612 if (!spcm) 613 return -EINVAL; 614 615 spcm_dbg(spcm, substream->stream, "Entry: close\n"); 616 617 err = snd_sof_pcm_platform_close(sdev, substream); 618 if (err < 0) { 619 spcm_err(spcm, substream->stream, 620 "platform pcm close failed %d\n", err); 621 /* 622 * keep going, no point in preventing the close 623 * from happening 624 */ 625 } 626 627 spcm->stream[substream->stream].substream = NULL; 628 629 return 0; 630} 631 632/* 633 * Pre-allocate playback/capture audio buffer pages. 634 * no need to explicitly release memory preallocated by sof_pcm_new in pcm_free 635 * snd_pcm_lib_preallocate_free_for_all() is called by the core. 636 */ 637static int sof_pcm_new(struct snd_soc_component *component, 638 struct snd_soc_pcm_runtime *rtd) 639{ 640 struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component); 641 struct snd_sof_pcm *spcm; 642 struct snd_pcm *pcm = rtd->pcm; 643 struct snd_soc_tplg_stream_caps *caps; 644 int stream = SNDRV_PCM_STREAM_PLAYBACK; 645 646 /* find SOF PCM for this RTD */ 647 spcm = snd_sof_find_spcm_dai(component, rtd); 648 if (!spcm) { 649 dev_warn(component->dev, "warn: can't find PCM with DAI ID %d\n", 650 rtd->dai_link->id); 651 return 0; 652 } 653 654 dev_dbg(spcm->scomp->dev, "pcm%u (%s): Entry: pcm_construct\n", 655 spcm->pcm.pcm_id, spcm->pcm.pcm_name); 656 657 /* do we need to pre-allocate playback audio buffer pages */ 658 if (!spcm->pcm.playback) 659 goto capture; 660 661 caps = &spcm->pcm.caps[stream]; 662 663 if (!pcm->streams[stream].substream) { 664 spcm_err(spcm, stream, "NULL playback substream!\n"); 665 return -EINVAL; 666 } 667 668 /* pre-allocate playback audio buffer pages */ 669 spcm_dbg(spcm, stream, "allocate %s playback DMA buffer size 0x%x max 0x%x\n", 670 caps->name, caps->buffer_size_min, caps->buffer_size_max); 671 672 snd_pcm_set_managed_buffer(pcm->streams[stream].substream, 673 SNDRV_DMA_TYPE_DEV_SG, sdev->dev, 674 0, le32_to_cpu(caps->buffer_size_max)); 675 676 /* Set the PCM device name for HDMI playback */ 677 if (!strncmp(pcm->id, "HDMI", 4)) { 678 int hdmi_idx; 679 680 /* 681 * Make sure that the name is in"HDMI<SPACE>x" format as this is 682 * expected by user space. 683 * See alsa-lib's __snd_pcm_info_eld_fixup_check() which is 684 * guarding the __snd_pcm_info_eld_fixup() in 685 * snd_ctl_hw_pcm_info() and snd_pcm_hw_info() library functions 686 */ 687 if (sscanf(pcm->id, "HDMI%d", &hdmi_idx) == 1) 688 snprintf(pcm->name, sizeof(pcm->name), "HDMI %d", 689 hdmi_idx); 690 else 691 strscpy(pcm->name, pcm->id, sizeof(pcm->name)); 692 } 693capture: 694 stream = SNDRV_PCM_STREAM_CAPTURE; 695 696 /* do we need to pre-allocate capture audio buffer pages */ 697 if (!spcm->pcm.capture) 698 return 0; 699 700 caps = &spcm->pcm.caps[stream]; 701 702 if (!pcm->streams[stream].substream) { 703 spcm_err(spcm, stream, "NULL capture substream!\n"); 704 return -EINVAL; 705 } 706 707 /* pre-allocate capture audio buffer pages */ 708 spcm_dbg(spcm, stream, "allocate %s capture DMA buffer size 0x%x max 0x%x\n", 709 caps->name, caps->buffer_size_min, caps->buffer_size_max); 710 711 snd_pcm_set_managed_buffer(pcm->streams[stream].substream, 712 SNDRV_DMA_TYPE_DEV_SG, sdev->dev, 713 0, le32_to_cpu(caps->buffer_size_max)); 714 715 return 0; 716} 717 718/* fixup the BE DAI link to match any values from topology */ 719int sof_pcm_dai_link_fixup(struct snd_soc_pcm_runtime *rtd, struct snd_pcm_hw_params *params) 720{ 721 struct snd_interval *rate = hw_param_interval(params, 722 SNDRV_PCM_HW_PARAM_RATE); 723 struct snd_interval *channels = hw_param_interval(params, 724 SNDRV_PCM_HW_PARAM_CHANNELS); 725 struct snd_mask *fmt = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT); 726 struct snd_soc_component *component = 727 snd_soc_rtdcom_lookup(rtd, SOF_AUDIO_PCM_DRV_NAME); 728 struct snd_sof_dai *dai = 729 snd_sof_find_dai(component, (char *)rtd->dai_link->name); 730 struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component); 731 const struct sof_ipc_pcm_ops *pcm_ops = sof_ipc_get_ops(sdev, pcm); 732 733 /* no topology exists for this BE, try a common configuration */ 734 if (!dai) { 735 dev_warn(component->dev, 736 "warning: no topology found for BE DAI %s config\n", 737 rtd->dai_link->name); 738 739 /* set 48k, stereo, 16bits by default */ 740 rate->min = 48000; 741 rate->max = 48000; 742 743 channels->min = 2; 744 channels->max = 2; 745 746 snd_mask_none(fmt); 747 snd_mask_set_format(fmt, SNDRV_PCM_FORMAT_S16_LE); 748 749 return 0; 750 } 751 752 if (pcm_ops && pcm_ops->dai_link_fixup) 753 return pcm_ops->dai_link_fixup(rtd, params); 754 755 return 0; 756} 757EXPORT_SYMBOL(sof_pcm_dai_link_fixup); 758 759static int sof_pcm_probe(struct snd_soc_component *component) 760{ 761 struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component); 762 struct snd_sof_pdata *plat_data = sdev->pdata; 763 const char *tplg_filename; 764 int ret; 765 766 /* 767 * make sure the device is pm_runtime_active before loading the 768 * topology and initiating IPC or bus transactions 769 */ 770 ret = pm_runtime_resume_and_get(component->dev); 771 if (ret < 0 && ret != -EACCES) 772 return ret; 773 774 /* load the default topology */ 775 sdev->component = component; 776 777 tplg_filename = devm_kasprintf(sdev->dev, GFP_KERNEL, 778 "%s/%s", 779 plat_data->tplg_filename_prefix, 780 plat_data->tplg_filename); 781 if (!tplg_filename) { 782 ret = -ENOMEM; 783 goto pm_error; 784 } 785 786 ret = snd_sof_load_topology(component, tplg_filename); 787 if (ret < 0) 788 dev_err(component->dev, "error: failed to load DSP topology %d\n", 789 ret); 790 791pm_error: 792 pm_runtime_put_autosuspend(component->dev); 793 794 return ret; 795} 796 797static void sof_pcm_remove(struct snd_soc_component *component) 798{ 799 /* remove topology */ 800 snd_soc_tplg_component_remove(component); 801} 802 803static int sof_pcm_ack(struct snd_soc_component *component, 804 struct snd_pcm_substream *substream) 805{ 806 struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component); 807 808 return snd_sof_pcm_platform_ack(sdev, substream); 809} 810 811static snd_pcm_sframes_t sof_pcm_delay(struct snd_soc_component *component, 812 struct snd_pcm_substream *substream) 813{ 814 struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component); 815 const struct sof_ipc_pcm_ops *pcm_ops = sof_ipc_get_ops(sdev, pcm); 816 817 if (pcm_ops && pcm_ops->delay) 818 return pcm_ops->delay(component, substream); 819 820 return 0; 821} 822 823void snd_sof_new_platform_drv(struct snd_sof_dev *sdev) 824{ 825 struct snd_soc_component_driver *pd = &sdev->plat_drv; 826 struct snd_sof_pdata *plat_data = sdev->pdata; 827 const char *drv_name; 828 829 if (plat_data->machine) 830 drv_name = plat_data->machine->drv_name; 831 else if (plat_data->of_machine) 832 drv_name = plat_data->of_machine->drv_name; 833 else 834 drv_name = NULL; 835 836 pd->name = "sof-audio-component"; 837 pd->probe = sof_pcm_probe; 838 pd->remove = sof_pcm_remove; 839 pd->open = sof_pcm_open; 840 pd->close = sof_pcm_close; 841 pd->hw_params = sof_pcm_hw_params; 842 pd->prepare = sof_pcm_prepare; 843 pd->hw_free = sof_pcm_hw_free; 844 pd->trigger = sof_pcm_trigger; 845 pd->pointer = sof_pcm_pointer; 846 pd->ack = sof_pcm_ack; 847 pd->delay = sof_pcm_delay; 848 849#if IS_ENABLED(CONFIG_SND_SOC_SOF_COMPRESS) 850 pd->compress_ops = &sof_compressed_ops; 851#endif 852 853 pd->pcm_construct = sof_pcm_new; 854 pd->ignore_machine = drv_name; 855 pd->be_pcm_base = SOF_BE_PCM_BASE; 856 pd->use_dai_pcm_id = true; 857 pd->topology_name_prefix = "sof"; 858 859 /* increment module refcount when a pcm is opened */ 860 pd->module_get_upon_open = 1; 861 862 pd->legacy_dai_naming = 1; 863 864 /* 865 * The fixup is only needed when the DSP is in use as with the DSPless 866 * mode we are directly using the audio interface 867 */ 868 if (!sdev->dspless_mode_selected) 869 pd->be_hw_params_fixup = sof_pcm_dai_link_fixup; 870}