1 // SPDX-License-Identifier: (GPL-2.0 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 // 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 "sof-priv.h" 17 #include "sof-audio.h" 18 #include "ops.h" 19 20 /* Create DMA buffer page table for DSP */ 21 static int create_page_table(struct snd_soc_component *component, 22 struct snd_pcm_substream *substream, 23 unsigned char *dma_area, size_t size) 24 { 25 struct snd_soc_pcm_runtime *rtd = substream->private_data; 26 struct snd_sof_pcm *spcm; 27 struct snd_dma_buffer *dmab = snd_pcm_get_dma_buf(substream); 28 int stream = substream->stream; 29 30 spcm = snd_sof_find_spcm_dai(component, rtd); 31 if (!spcm) 32 return -EINVAL; 33 34 return snd_sof_create_page_table(component->dev, dmab, 35 spcm->stream[stream].page_table.area, size); 36 } 37 38 static int sof_pcm_dsp_params(struct snd_sof_pcm *spcm, struct snd_pcm_substream *substream, 39 const struct sof_ipc_pcm_params_reply *reply) 40 { 41 struct snd_soc_component *scomp = spcm->scomp; 42 struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); 43 44 /* validate offset */ 45 int ret = snd_sof_ipc_pcm_params(sdev, substream, reply); 46 47 if (ret < 0) 48 dev_err(scomp->dev, "error: got wrong reply for PCM %d\n", 49 spcm->pcm.pcm_id); 50 51 return ret; 52 } 53 54 /* 55 * sof pcm period elapse work 56 */ 57 static void sof_pcm_period_elapsed_work(struct work_struct *work) 58 { 59 struct snd_sof_pcm_stream *sps = 60 container_of(work, struct snd_sof_pcm_stream, 61 period_elapsed_work); 62 63 snd_pcm_period_elapsed(sps->substream); 64 } 65 66 /* 67 * sof pcm period elapse, this could be called at irq thread context. 68 */ 69 void snd_sof_pcm_period_elapsed(struct snd_pcm_substream *substream) 70 { 71 struct snd_soc_pcm_runtime *rtd = substream->private_data; 72 struct snd_soc_component *component = 73 snd_soc_rtdcom_lookup(rtd, SOF_AUDIO_PCM_DRV_NAME); 74 struct snd_sof_pcm *spcm; 75 76 spcm = snd_sof_find_spcm_dai(component, rtd); 77 if (!spcm) { 78 dev_err(component->dev, 79 "error: period elapsed for unknown stream!\n"); 80 return; 81 } 82 83 /* 84 * snd_pcm_period_elapsed() can be called in interrupt context 85 * before IRQ_HANDLED is returned. Inside snd_pcm_period_elapsed(), 86 * when the PCM is done draining or xrun happened, a STOP IPC will 87 * then be sent and this IPC will hit IPC timeout. 88 * To avoid sending IPC before the previous IPC is handled, we 89 * schedule delayed work here to call the snd_pcm_period_elapsed(). 90 */ 91 schedule_work(&spcm->stream[substream->stream].period_elapsed_work); 92 } 93 EXPORT_SYMBOL(snd_sof_pcm_period_elapsed); 94 95 static int sof_pcm_dsp_pcm_free(struct snd_pcm_substream *substream, 96 struct snd_sof_dev *sdev, 97 struct snd_sof_pcm *spcm) 98 { 99 struct sof_ipc_stream stream; 100 struct sof_ipc_reply reply; 101 int ret; 102 103 stream.hdr.size = sizeof(stream); 104 stream.hdr.cmd = SOF_IPC_GLB_STREAM_MSG | SOF_IPC_STREAM_PCM_FREE; 105 stream.comp_id = spcm->stream[substream->stream].comp_id; 106 107 /* send IPC to the DSP */ 108 ret = sof_ipc_tx_message(sdev->ipc, stream.hdr.cmd, &stream, 109 sizeof(stream), &reply, sizeof(reply)); 110 if (!ret) 111 spcm->prepared[substream->stream] = false; 112 113 return ret; 114 } 115 116 static 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_soc_pcm_runtime *rtd = substream->private_data; 121 struct snd_pcm_runtime *runtime = substream->runtime; 122 struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component); 123 struct snd_sof_pcm *spcm; 124 struct sof_ipc_pcm_params pcm; 125 struct sof_ipc_pcm_params_reply ipc_params_reply; 126 int ret; 127 128 /* nothing to do for BE */ 129 if (rtd->dai_link->no_pcm) 130 return 0; 131 132 spcm = snd_sof_find_spcm_dai(component, rtd); 133 if (!spcm) 134 return -EINVAL; 135 136 /* 137 * Handle repeated calls to hw_params() without free_pcm() in 138 * between. At least ALSA OSS emulation depends on this. 139 */ 140 if (spcm->prepared[substream->stream]) { 141 ret = sof_pcm_dsp_pcm_free(substream, sdev, spcm); 142 if (ret < 0) 143 return ret; 144 } 145 146 dev_dbg(component->dev, "pcm: hw params stream %d dir %d\n", 147 spcm->pcm.pcm_id, substream->stream); 148 149 memset(&pcm, 0, sizeof(pcm)); 150 151 /* create compressed page table for audio firmware */ 152 if (runtime->buffer_changed) { 153 ret = create_page_table(component, substream, runtime->dma_area, 154 runtime->dma_bytes); 155 if (ret < 0) 156 return ret; 157 } 158 159 /* number of pages should be rounded up */ 160 pcm.params.buffer.pages = PFN_UP(runtime->dma_bytes); 161 162 /* set IPC PCM parameters */ 163 pcm.hdr.size = sizeof(pcm); 164 pcm.hdr.cmd = SOF_IPC_GLB_STREAM_MSG | SOF_IPC_STREAM_PCM_PARAMS; 165 pcm.comp_id = spcm->stream[substream->stream].comp_id; 166 pcm.params.hdr.size = sizeof(pcm.params); 167 pcm.params.buffer.phy_addr = 168 spcm->stream[substream->stream].page_table.addr; 169 pcm.params.buffer.size = runtime->dma_bytes; 170 pcm.params.direction = substream->stream; 171 pcm.params.sample_valid_bytes = params_width(params) >> 3; 172 pcm.params.buffer_fmt = SOF_IPC_BUFFER_INTERLEAVED; 173 pcm.params.rate = params_rate(params); 174 pcm.params.channels = params_channels(params); 175 pcm.params.host_period_bytes = params_period_bytes(params); 176 177 /* container size */ 178 ret = snd_pcm_format_physical_width(params_format(params)); 179 if (ret < 0) 180 return ret; 181 pcm.params.sample_container_bytes = ret >> 3; 182 183 /* format */ 184 switch (params_format(params)) { 185 case SNDRV_PCM_FORMAT_S16: 186 pcm.params.frame_fmt = SOF_IPC_FRAME_S16_LE; 187 break; 188 case SNDRV_PCM_FORMAT_S24: 189 pcm.params.frame_fmt = SOF_IPC_FRAME_S24_4LE; 190 break; 191 case SNDRV_PCM_FORMAT_S32: 192 pcm.params.frame_fmt = SOF_IPC_FRAME_S32_LE; 193 break; 194 case SNDRV_PCM_FORMAT_FLOAT: 195 pcm.params.frame_fmt = SOF_IPC_FRAME_FLOAT; 196 break; 197 default: 198 return -EINVAL; 199 } 200 201 /* firmware already configured host stream */ 202 ret = snd_sof_pcm_platform_hw_params(sdev, 203 substream, 204 params, 205 &pcm.params); 206 if (ret < 0) { 207 dev_err(component->dev, "error: platform hw params failed\n"); 208 return ret; 209 } 210 211 dev_dbg(component->dev, "stream_tag %d", pcm.params.stream_tag); 212 213 /* send IPC to the DSP */ 214 ret = sof_ipc_tx_message(sdev->ipc, pcm.hdr.cmd, &pcm, sizeof(pcm), 215 &ipc_params_reply, sizeof(ipc_params_reply)); 216 if (ret < 0) { 217 dev_err(component->dev, "error: hw params ipc failed for stream %d\n", 218 pcm.params.stream_tag); 219 return ret; 220 } 221 222 ret = sof_pcm_dsp_params(spcm, substream, &ipc_params_reply); 223 if (ret < 0) 224 return ret; 225 226 spcm->prepared[substream->stream] = true; 227 228 /* save pcm hw_params */ 229 memcpy(&spcm->params[substream->stream], params, sizeof(*params)); 230 231 return ret; 232 } 233 234 static int sof_pcm_hw_free(struct snd_soc_component *component, 235 struct snd_pcm_substream *substream) 236 { 237 struct snd_soc_pcm_runtime *rtd = substream->private_data; 238 struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component); 239 struct snd_sof_pcm *spcm; 240 int ret, err = 0; 241 242 /* nothing to do for BE */ 243 if (rtd->dai_link->no_pcm) 244 return 0; 245 246 spcm = snd_sof_find_spcm_dai(component, rtd); 247 if (!spcm) 248 return -EINVAL; 249 250 dev_dbg(component->dev, "pcm: free stream %d dir %d\n", 251 spcm->pcm.pcm_id, substream->stream); 252 253 if (spcm->prepared[substream->stream]) { 254 ret = sof_pcm_dsp_pcm_free(substream, sdev, spcm); 255 if (ret < 0) 256 err = ret; 257 } 258 259 cancel_work_sync(&spcm->stream[substream->stream].period_elapsed_work); 260 261 ret = snd_sof_pcm_platform_hw_free(sdev, substream); 262 if (ret < 0) { 263 dev_err(component->dev, "error: platform hw free failed\n"); 264 err = ret; 265 } 266 267 return err; 268 } 269 270 static int sof_pcm_prepare(struct snd_soc_component *component, 271 struct snd_pcm_substream *substream) 272 { 273 struct snd_soc_pcm_runtime *rtd = substream->private_data; 274 struct snd_sof_pcm *spcm; 275 int ret; 276 277 /* nothing to do for BE */ 278 if (rtd->dai_link->no_pcm) 279 return 0; 280 281 spcm = snd_sof_find_spcm_dai(component, rtd); 282 if (!spcm) 283 return -EINVAL; 284 285 if (spcm->prepared[substream->stream]) 286 return 0; 287 288 dev_dbg(component->dev, "pcm: prepare stream %d dir %d\n", 289 spcm->pcm.pcm_id, substream->stream); 290 291 /* set hw_params */ 292 ret = sof_pcm_hw_params(component, 293 substream, &spcm->params[substream->stream]); 294 if (ret < 0) { 295 dev_err(component->dev, 296 "error: set pcm hw_params after resume\n"); 297 return ret; 298 } 299 300 return 0; 301 } 302 303 /* 304 * FE dai link trigger actions are always executed in non-atomic context because 305 * they involve IPC's. 306 */ 307 static int sof_pcm_trigger(struct snd_soc_component *component, 308 struct snd_pcm_substream *substream, int cmd) 309 { 310 struct snd_soc_pcm_runtime *rtd = substream->private_data; 311 struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component); 312 struct snd_sof_pcm *spcm; 313 struct sof_ipc_stream stream; 314 struct sof_ipc_reply reply; 315 bool reset_hw_params = false; 316 bool ipc_first = false; 317 int ret; 318 319 /* nothing to do for BE */ 320 if (rtd->dai_link->no_pcm) 321 return 0; 322 323 spcm = snd_sof_find_spcm_dai(component, rtd); 324 if (!spcm) 325 return -EINVAL; 326 327 dev_dbg(component->dev, "pcm: trigger stream %d dir %d cmd %d\n", 328 spcm->pcm.pcm_id, substream->stream, cmd); 329 330 stream.hdr.size = sizeof(stream); 331 stream.hdr.cmd = SOF_IPC_GLB_STREAM_MSG; 332 stream.comp_id = spcm->stream[substream->stream].comp_id; 333 334 switch (cmd) { 335 case SNDRV_PCM_TRIGGER_PAUSE_PUSH: 336 stream.hdr.cmd |= SOF_IPC_STREAM_TRIG_PAUSE; 337 ipc_first = true; 338 break; 339 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: 340 stream.hdr.cmd |= SOF_IPC_STREAM_TRIG_RELEASE; 341 break; 342 case SNDRV_PCM_TRIGGER_RESUME: 343 if (spcm->stream[substream->stream].suspend_ignored) { 344 /* 345 * this case will be triggered when INFO_RESUME is 346 * supported, no need to resume streams that remained 347 * enabled in D0ix. 348 */ 349 spcm->stream[substream->stream].suspend_ignored = false; 350 return 0; 351 } 352 353 /* set up hw_params */ 354 ret = sof_pcm_prepare(component, substream); 355 if (ret < 0) { 356 dev_err(component->dev, 357 "error: failed to set up hw_params upon resume\n"); 358 return ret; 359 } 360 361 /* fallthrough */ 362 case SNDRV_PCM_TRIGGER_START: 363 if (spcm->stream[substream->stream].suspend_ignored) { 364 /* 365 * This case will be triggered when INFO_RESUME is 366 * not supported, no need to re-start streams that 367 * remained enabled in D0ix. 368 */ 369 spcm->stream[substream->stream].suspend_ignored = false; 370 return 0; 371 } 372 stream.hdr.cmd |= SOF_IPC_STREAM_TRIG_START; 373 break; 374 case SNDRV_PCM_TRIGGER_SUSPEND: 375 if (sdev->s0_suspend && 376 spcm->stream[substream->stream].d0i3_compatible) { 377 /* 378 * trap the event, not sending trigger stop to 379 * prevent the FW pipelines from being stopped, 380 * and mark the flag to ignore the upcoming DAPM 381 * PM events. 382 */ 383 spcm->stream[substream->stream].suspend_ignored = true; 384 return 0; 385 } 386 /* fallthrough */ 387 case SNDRV_PCM_TRIGGER_STOP: 388 stream.hdr.cmd |= SOF_IPC_STREAM_TRIG_STOP; 389 ipc_first = true; 390 reset_hw_params = true; 391 break; 392 default: 393 dev_err(component->dev, "error: unhandled trigger cmd %d\n", 394 cmd); 395 return -EINVAL; 396 } 397 398 /* 399 * DMA and IPC sequence is different for start and stop. Need to send 400 * STOP IPC before stop DMA 401 */ 402 if (!ipc_first) 403 snd_sof_pcm_platform_trigger(sdev, substream, cmd); 404 405 /* send IPC to the DSP */ 406 ret = sof_ipc_tx_message(sdev->ipc, stream.hdr.cmd, &stream, 407 sizeof(stream), &reply, sizeof(reply)); 408 409 /* need to STOP DMA even if STOP IPC failed */ 410 if (ipc_first) 411 snd_sof_pcm_platform_trigger(sdev, substream, cmd); 412 413 /* free PCM if reset_hw_params is set and the STOP IPC is successful */ 414 if (!ret && reset_hw_params) 415 ret = sof_pcm_dsp_pcm_free(substream, sdev, spcm); 416 417 return ret; 418 } 419 420 static snd_pcm_uframes_t sof_pcm_pointer(struct snd_soc_component *component, 421 struct snd_pcm_substream *substream) 422 { 423 struct snd_soc_pcm_runtime *rtd = substream->private_data; 424 struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component); 425 struct snd_sof_pcm *spcm; 426 snd_pcm_uframes_t host, dai; 427 428 /* nothing to do for BE */ 429 if (rtd->dai_link->no_pcm) 430 return 0; 431 432 /* use dsp ops pointer callback directly if set */ 433 if (sof_ops(sdev)->pcm_pointer) 434 return sof_ops(sdev)->pcm_pointer(sdev, substream); 435 436 spcm = snd_sof_find_spcm_dai(component, rtd); 437 if (!spcm) 438 return -EINVAL; 439 440 /* read position from DSP */ 441 host = bytes_to_frames(substream->runtime, 442 spcm->stream[substream->stream].posn.host_posn); 443 dai = bytes_to_frames(substream->runtime, 444 spcm->stream[substream->stream].posn.dai_posn); 445 446 dev_dbg(component->dev, 447 "PCM: stream %d dir %d DMA position %lu DAI position %lu\n", 448 spcm->pcm.pcm_id, substream->stream, host, dai); 449 450 return host; 451 } 452 453 static int sof_pcm_open(struct snd_soc_component *component, 454 struct snd_pcm_substream *substream) 455 { 456 struct snd_soc_pcm_runtime *rtd = substream->private_data; 457 struct snd_pcm_runtime *runtime = substream->runtime; 458 struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component); 459 const struct snd_sof_dsp_ops *ops = sof_ops(sdev); 460 struct snd_sof_pcm *spcm; 461 struct snd_soc_tplg_stream_caps *caps; 462 int ret; 463 464 /* nothing to do for BE */ 465 if (rtd->dai_link->no_pcm) 466 return 0; 467 468 spcm = snd_sof_find_spcm_dai(component, rtd); 469 if (!spcm) 470 return -EINVAL; 471 472 dev_dbg(component->dev, "pcm: open stream %d dir %d\n", 473 spcm->pcm.pcm_id, substream->stream); 474 475 INIT_WORK(&spcm->stream[substream->stream].period_elapsed_work, 476 sof_pcm_period_elapsed_work); 477 478 caps = &spcm->pcm.caps[substream->stream]; 479 480 /* set any runtime constraints based on topology */ 481 snd_pcm_hw_constraint_step(substream->runtime, 0, 482 SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 483 le32_to_cpu(caps->period_size_min)); 484 snd_pcm_hw_constraint_step(substream->runtime, 0, 485 SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 486 le32_to_cpu(caps->period_size_min)); 487 488 /* set runtime config */ 489 runtime->hw.info = ops->hw_info; /* platform-specific */ 490 491 runtime->hw.formats = le64_to_cpu(caps->formats); 492 runtime->hw.period_bytes_min = le32_to_cpu(caps->period_size_min); 493 runtime->hw.period_bytes_max = le32_to_cpu(caps->period_size_max); 494 runtime->hw.periods_min = le32_to_cpu(caps->periods_min); 495 runtime->hw.periods_max = le32_to_cpu(caps->periods_max); 496 497 /* 498 * caps->buffer_size_min is not used since the 499 * snd_pcm_hardware structure only defines buffer_bytes_max 500 */ 501 runtime->hw.buffer_bytes_max = le32_to_cpu(caps->buffer_size_max); 502 503 dev_dbg(component->dev, "period min %zd max %zd bytes\n", 504 runtime->hw.period_bytes_min, 505 runtime->hw.period_bytes_max); 506 dev_dbg(component->dev, "period count %d max %d\n", 507 runtime->hw.periods_min, 508 runtime->hw.periods_max); 509 dev_dbg(component->dev, "buffer max %zd bytes\n", 510 runtime->hw.buffer_bytes_max); 511 512 /* set wait time - TODO: come from topology */ 513 substream->wait_time = 500; 514 515 spcm->stream[substream->stream].posn.host_posn = 0; 516 spcm->stream[substream->stream].posn.dai_posn = 0; 517 spcm->stream[substream->stream].substream = substream; 518 spcm->prepared[substream->stream] = false; 519 520 ret = snd_sof_pcm_platform_open(sdev, substream); 521 if (ret < 0) 522 dev_err(component->dev, "error: pcm open failed %d\n", ret); 523 524 return ret; 525 } 526 527 static int sof_pcm_close(struct snd_soc_component *component, 528 struct snd_pcm_substream *substream) 529 { 530 struct snd_soc_pcm_runtime *rtd = substream->private_data; 531 struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component); 532 struct snd_sof_pcm *spcm; 533 int err; 534 535 /* nothing to do for BE */ 536 if (rtd->dai_link->no_pcm) 537 return 0; 538 539 spcm = snd_sof_find_spcm_dai(component, rtd); 540 if (!spcm) 541 return -EINVAL; 542 543 dev_dbg(component->dev, "pcm: close stream %d dir %d\n", 544 spcm->pcm.pcm_id, substream->stream); 545 546 err = snd_sof_pcm_platform_close(sdev, substream); 547 if (err < 0) { 548 dev_err(component->dev, "error: pcm close failed %d\n", 549 err); 550 /* 551 * keep going, no point in preventing the close 552 * from happening 553 */ 554 } 555 556 return 0; 557 } 558 559 /* 560 * Pre-allocate playback/capture audio buffer pages. 561 * no need to explicitly release memory preallocated by sof_pcm_new in pcm_free 562 * snd_pcm_lib_preallocate_free_for_all() is called by the core. 563 */ 564 static int sof_pcm_new(struct snd_soc_component *component, 565 struct snd_soc_pcm_runtime *rtd) 566 { 567 struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component); 568 struct snd_sof_pcm *spcm; 569 struct snd_pcm *pcm = rtd->pcm; 570 struct snd_soc_tplg_stream_caps *caps; 571 int stream = SNDRV_PCM_STREAM_PLAYBACK; 572 573 /* find SOF PCM for this RTD */ 574 spcm = snd_sof_find_spcm_dai(component, rtd); 575 if (!spcm) { 576 dev_warn(component->dev, "warn: can't find PCM with DAI ID %d\n", 577 rtd->dai_link->id); 578 return 0; 579 } 580 581 dev_dbg(component->dev, "creating new PCM %s\n", spcm->pcm.pcm_name); 582 583 /* do we need to pre-allocate playback audio buffer pages */ 584 if (!spcm->pcm.playback) 585 goto capture; 586 587 caps = &spcm->pcm.caps[stream]; 588 589 /* pre-allocate playback audio buffer pages */ 590 dev_dbg(component->dev, 591 "spcm: allocate %s playback DMA buffer size 0x%x max 0x%x\n", 592 caps->name, caps->buffer_size_min, caps->buffer_size_max); 593 594 if (!pcm->streams[stream].substream) { 595 dev_err(component->dev, "error: NULL playback substream!\n"); 596 return -EINVAL; 597 } 598 599 snd_pcm_set_managed_buffer(pcm->streams[stream].substream, 600 SNDRV_DMA_TYPE_DEV_SG, sdev->dev, 601 le32_to_cpu(caps->buffer_size_min), 602 le32_to_cpu(caps->buffer_size_max)); 603 capture: 604 stream = SNDRV_PCM_STREAM_CAPTURE; 605 606 /* do we need to pre-allocate capture audio buffer pages */ 607 if (!spcm->pcm.capture) 608 return 0; 609 610 caps = &spcm->pcm.caps[stream]; 611 612 /* pre-allocate capture audio buffer pages */ 613 dev_dbg(component->dev, 614 "spcm: allocate %s capture DMA buffer size 0x%x max 0x%x\n", 615 caps->name, caps->buffer_size_min, caps->buffer_size_max); 616 617 if (!pcm->streams[stream].substream) { 618 dev_err(component->dev, "error: NULL capture substream!\n"); 619 return -EINVAL; 620 } 621 622 snd_pcm_set_managed_buffer(pcm->streams[stream].substream, 623 SNDRV_DMA_TYPE_DEV_SG, sdev->dev, 624 le32_to_cpu(caps->buffer_size_min), 625 le32_to_cpu(caps->buffer_size_max)); 626 627 return 0; 628 } 629 630 /* fixup the BE DAI link to match any values from topology */ 631 static int sof_pcm_dai_link_fixup(struct snd_soc_pcm_runtime *rtd, 632 struct snd_pcm_hw_params *params) 633 { 634 struct snd_interval *rate = hw_param_interval(params, 635 SNDRV_PCM_HW_PARAM_RATE); 636 struct snd_interval *channels = hw_param_interval(params, 637 SNDRV_PCM_HW_PARAM_CHANNELS); 638 struct snd_mask *fmt = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT); 639 struct snd_soc_component *component = 640 snd_soc_rtdcom_lookup(rtd, SOF_AUDIO_PCM_DRV_NAME); 641 struct snd_sof_dai *dai = 642 snd_sof_find_dai(component, (char *)rtd->dai_link->name); 643 644 /* no topology exists for this BE, try a common configuration */ 645 if (!dai) { 646 dev_warn(component->dev, 647 "warning: no topology found for BE DAI %s config\n", 648 rtd->dai_link->name); 649 650 /* set 48k, stereo, 16bits by default */ 651 rate->min = 48000; 652 rate->max = 48000; 653 654 channels->min = 2; 655 channels->max = 2; 656 657 snd_mask_none(fmt); 658 snd_mask_set_format(fmt, SNDRV_PCM_FORMAT_S16_LE); 659 660 return 0; 661 } 662 663 /* read format from topology */ 664 snd_mask_none(fmt); 665 666 switch (dai->comp_dai.config.frame_fmt) { 667 case SOF_IPC_FRAME_S16_LE: 668 snd_mask_set_format(fmt, SNDRV_PCM_FORMAT_S16_LE); 669 break; 670 case SOF_IPC_FRAME_S24_4LE: 671 snd_mask_set_format(fmt, SNDRV_PCM_FORMAT_S24_LE); 672 break; 673 case SOF_IPC_FRAME_S32_LE: 674 snd_mask_set_format(fmt, SNDRV_PCM_FORMAT_S32_LE); 675 break; 676 default: 677 dev_err(component->dev, "error: No available DAI format!\n"); 678 return -EINVAL; 679 } 680 681 /* read rate and channels from topology */ 682 switch (dai->dai_config->type) { 683 case SOF_DAI_INTEL_SSP: 684 rate->min = dai->dai_config->ssp.fsync_rate; 685 rate->max = dai->dai_config->ssp.fsync_rate; 686 channels->min = dai->dai_config->ssp.tdm_slots; 687 channels->max = dai->dai_config->ssp.tdm_slots; 688 689 dev_dbg(component->dev, 690 "rate_min: %d rate_max: %d\n", rate->min, rate->max); 691 dev_dbg(component->dev, 692 "channels_min: %d channels_max: %d\n", 693 channels->min, channels->max); 694 695 break; 696 case SOF_DAI_INTEL_DMIC: 697 /* DMIC only supports 16 or 32 bit formats */ 698 if (dai->comp_dai.config.frame_fmt == SOF_IPC_FRAME_S24_4LE) { 699 dev_err(component->dev, 700 "error: invalid fmt %d for DAI type %d\n", 701 dai->comp_dai.config.frame_fmt, 702 dai->dai_config->type); 703 } 704 break; 705 case SOF_DAI_INTEL_HDA: 706 /* do nothing for HDA dai_link */ 707 break; 708 case SOF_DAI_INTEL_ALH: 709 /* do nothing for ALH dai_link */ 710 break; 711 case SOF_DAI_IMX_ESAI: 712 channels->min = dai->dai_config->esai.tdm_slots; 713 channels->max = dai->dai_config->esai.tdm_slots; 714 715 dev_dbg(component->dev, 716 "channels_min: %d channels_max: %d\n", 717 channels->min, channels->max); 718 break; 719 case SOF_DAI_IMX_SAI: 720 channels->min = dai->dai_config->sai.tdm_slots; 721 channels->max = dai->dai_config->sai.tdm_slots; 722 723 dev_dbg(component->dev, 724 "channels_min: %d channels_max: %d\n", 725 channels->min, channels->max); 726 break; 727 default: 728 dev_err(component->dev, "error: invalid DAI type %d\n", 729 dai->dai_config->type); 730 break; 731 } 732 733 return 0; 734 } 735 736 static int sof_pcm_probe(struct snd_soc_component *component) 737 { 738 struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component); 739 struct snd_sof_pdata *plat_data = sdev->pdata; 740 const char *tplg_filename; 741 int ret; 742 743 /* load the default topology */ 744 sdev->component = component; 745 746 tplg_filename = devm_kasprintf(sdev->dev, GFP_KERNEL, 747 "%s/%s", 748 plat_data->tplg_filename_prefix, 749 plat_data->tplg_filename); 750 if (!tplg_filename) 751 return -ENOMEM; 752 753 ret = snd_sof_load_topology(component, tplg_filename); 754 if (ret < 0) { 755 dev_err(component->dev, "error: failed to load DSP topology %d\n", 756 ret); 757 return ret; 758 } 759 760 return ret; 761 } 762 763 static void sof_pcm_remove(struct snd_soc_component *component) 764 { 765 /* remove topology */ 766 snd_soc_tplg_component_remove(component, SND_SOC_TPLG_INDEX_ALL); 767 } 768 769 void snd_sof_new_platform_drv(struct snd_sof_dev *sdev) 770 { 771 struct snd_soc_component_driver *pd = &sdev->plat_drv; 772 struct snd_sof_pdata *plat_data = sdev->pdata; 773 const char *drv_name; 774 775 drv_name = plat_data->machine->drv_name; 776 777 pd->name = "sof-audio-component"; 778 pd->probe = sof_pcm_probe; 779 pd->remove = sof_pcm_remove; 780 pd->open = sof_pcm_open; 781 pd->close = sof_pcm_close; 782 pd->hw_params = sof_pcm_hw_params; 783 pd->prepare = sof_pcm_prepare; 784 pd->hw_free = sof_pcm_hw_free; 785 pd->trigger = sof_pcm_trigger; 786 pd->pointer = sof_pcm_pointer; 787 788 #if IS_ENABLED(CONFIG_SND_SOC_SOF_COMPRESS) 789 pd->compr_ops = &sof_compressed_ops; 790 #endif 791 pd->pcm_construct = sof_pcm_new; 792 pd->ignore_machine = drv_name; 793 pd->be_hw_params_fixup = sof_pcm_dai_link_fixup; 794 pd->be_pcm_base = SOF_BE_PCM_BASE; 795 pd->use_dai_pcm_id = true; 796 pd->topology_name_prefix = "sof"; 797 798 /* increment module refcount when a pcm is opened */ 799 pd->module_get_upon_open = 1; 800 } 801