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